proto_memory_estimations.cc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Copyright (c) 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Keep this file in sync with the .proto files in this directory.
  5. #include "components/sync/protocol/proto_memory_estimations.h"
  6. #include <string>
  7. #include "base/trace_event/memory_usage_estimator.h"
  8. #include "components/sync/protocol/data_type_progress_marker.pb.h"
  9. #include "components/sync/protocol/entity_metadata.pb.h"
  10. #include "components/sync/protocol/entity_specifics.pb.h"
  11. #include "components/sync/protocol/model_type_state.pb.h"
  12. #include "components/sync/protocol/persisted_entity_data.pb.h"
  13. #include "components/sync/protocol/proto_visitors.h"
  14. #include "components/sync/protocol/sync_entity.pb.h"
  15. #include "components/sync/protocol/unique_position.pb.h"
  16. namespace {
  17. // This class is a VisitProtoFields()-compatible visitor that estimates
  18. // proto's memory usage:
  19. //
  20. // MemoryUsageVisitor visitor;
  21. // VisitProtoFields(visitor, proto);
  22. // size_t memory_usage = visitor.memory_usage();
  23. //
  24. class MemoryUsageVisitor {
  25. public:
  26. MemoryUsageVisitor() = default;
  27. size_t memory_usage() const { return memory_usage_; }
  28. template <class P>
  29. void VisitBytes(const P& parent_proto,
  30. const char* field_name,
  31. const std::string& field) {
  32. // Delegate to Visit(..., const std::string&) below.
  33. Visit(parent_proto, field_name, field);
  34. }
  35. template <class P, class E>
  36. void VisitEnum(const P&, const char* field_name, E field) {}
  37. // Types derived from MessageLite (i.e. protos)
  38. template <class P, class F>
  39. typename std::enable_if<
  40. std::is_base_of<google::protobuf::MessageLite, F>::value>::type
  41. Visit(const P&, const char* field_name, const F& field) {
  42. using base::trace_event::EstimateMemoryUsage;
  43. // All object fields are dynamically allocated.
  44. memory_usage_ += sizeof(F) + EstimateMemoryUsage(field);
  45. }
  46. // Arithmetic types
  47. template <class P, class F>
  48. typename std::enable_if<std::is_arithmetic<F>::value>::type
  49. Visit(const P&, const char* field_name, const F& field) {
  50. // Arithmetic fields (integers, floats & bool) don't allocate.
  51. }
  52. // std::string
  53. template <class P>
  54. void Visit(const P&, const char* field_name, const std::string& field) {
  55. using base::trace_event::EstimateMemoryUsage;
  56. // All strings are of type ArenaStringPtr, which essentially
  57. // is std::string*.
  58. memory_usage_ += sizeof(std::string) + EstimateMemoryUsage(field);
  59. }
  60. // RepeatedPtrField
  61. template <class P, class F>
  62. void Visit(const P&,
  63. const char* field_name,
  64. const google::protobuf::RepeatedPtrField<F>& fields) {
  65. using base::trace_event::EstimateMemoryUsage;
  66. // Can't use RepeatedPtrField::SpaceUsedExcludingSelf() because it will
  67. // end up calling undefined TypeHandler::SpaceUsed() method.
  68. memory_usage_ += fields.Capacity() ? sizeof(void*) : 0; // header
  69. memory_usage_ += fields.Capacity() * sizeof(void*);
  70. for (const auto& field : fields) {
  71. memory_usage_ += sizeof(F) + EstimateMemoryUsage(field);
  72. }
  73. }
  74. // RepeatedField<arithmetic type>
  75. template <class P, class F>
  76. typename std::enable_if<std::is_arithmetic<F>::value>::type Visit(
  77. const P&,
  78. const char* field_name,
  79. const google::protobuf::RepeatedField<F>& fields) {
  80. memory_usage_ += fields.SpaceUsedExcludingSelf();
  81. // Arithmetic fields (integers, floats & bool) don't allocate, so no point
  82. // in iterating over |fields|.
  83. }
  84. // RepeatedField<std::string>
  85. template <class P>
  86. void Visit(const P&,
  87. const char* field_name,
  88. const google::protobuf::RepeatedField<std::string>& fields) {
  89. using base::trace_event::EstimateMemoryUsage;
  90. memory_usage_ += fields.SpaceUsedExcludingSelf();
  91. for (const auto& field : fields) {
  92. memory_usage_ += EstimateMemoryUsage(field);
  93. }
  94. }
  95. private:
  96. size_t memory_usage_ = 0;
  97. };
  98. } // namespace
  99. namespace sync_pb {
  100. template <class P>
  101. size_t EstimateMemoryUsage(const P& proto) {
  102. MemoryUsageVisitor visitor;
  103. syncer::VisitProtoFields(visitor, proto);
  104. return visitor.memory_usage();
  105. }
  106. // Explicit instantiations
  107. #define INSTANTIATE(Proto) \
  108. template size_t EstimateMemoryUsage<Proto>(const Proto&);
  109. INSTANTIATE(DataTypeContext)
  110. INSTANTIATE(DataTypeProgressMarker)
  111. INSTANTIATE(EntityMetadata)
  112. INSTANTIATE(EntitySpecifics)
  113. INSTANTIATE(ModelTypeState)
  114. INSTANTIATE(PersistedEntityData)
  115. INSTANTIATE(SyncEntity)
  116. INSTANTIATE(UniquePosition)
  117. } // namespace sync_pb