You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

arenaz_sampler.h 9.8 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
  31. #define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
  32. #include <atomic>
  33. #include <cstddef>
  34. #include <cstdint>
  35. // Must be included last.
  36. #include <google/protobuf/port_def.inc>
  37. namespace google
  38. {
  39. namespace protobuf
  40. {
  41. namespace internal
  42. {
  43. #if defined(PROTOBUF_ARENAZ_SAMPLE)
  44. struct ThreadSafeArenaStats;
  45. void RecordResetSlow(ThreadSafeArenaStats* info);
  46. void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested, size_t allocated, size_t wasted);
  47. // Stores information about a sampled thread safe arena. All mutations to this
  48. // *must* be made through `Record*` functions below. All reads from this *must*
  49. // only occur in the callback to `ThreadSafeArenazSampler::Iterate`.
  50. struct ThreadSafeArenaStats : public absl::profiling_internal::Sample<ThreadSafeArenaStats>
  51. {
  52. // Constructs the object but does not fill in any fields.
  53. ThreadSafeArenaStats();
  54. ~ThreadSafeArenaStats();
  55. // Puts the object into a clean state, fills in the logically `const` members,
  56. // blocking for any readers that are currently sampling the object.
  57. void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
  58. // These fields are mutated by the various Record* APIs and need to be
  59. // thread-safe.
  60. std::atomic<int> num_allocations;
  61. std::atomic<int> num_resets;
  62. std::atomic<size_t> bytes_requested;
  63. std::atomic<size_t> bytes_allocated;
  64. std::atomic<size_t> bytes_wasted;
  65. // Records the largest size an arena ever had. Maintained across resets.
  66. std::atomic<size_t> max_bytes_allocated;
  67. // Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the
  68. // underlying arena. The field is maintained across resets.
  69. std::atomic<uint64_t> thread_ids;
  70. // All of the fields below are set by `PrepareForSampling`, they must not
  71. // be mutated in `Record*` functions. They are logically `const` in that
  72. // sense. These are guarded by init_mu, but that is not externalized to
  73. // clients, who can only read them during
  74. // `ThreadSafeArenazSampler::Iterate` which will hold the lock.
  75. static constexpr int kMaxStackDepth = 64;
  76. int32_t depth;
  77. void* stack[kMaxStackDepth];
  78. static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested, size_t allocated, size_t wasted)
  79. {
  80. if (PROTOBUF_PREDICT_TRUE(info == nullptr))
  81. return;
  82. RecordAllocateSlow(info, requested, allocated, wasted);
  83. }
  84. };
  85. ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
  86. void UnsampleSlow(ThreadSafeArenaStats* info);
  87. class ThreadSafeArenaStatsHandle
  88. {
  89. public:
  90. explicit ThreadSafeArenaStatsHandle() = default;
  91. explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info) :
  92. info_(info)
  93. {
  94. }
  95. ~ThreadSafeArenaStatsHandle()
  96. {
  97. if (PROTOBUF_PREDICT_TRUE(info_ == nullptr))
  98. return;
  99. UnsampleSlow(info_);
  100. }
  101. ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept
  102. :
  103. info_(absl::exchange(other.info_, nullptr))
  104. {
  105. }
  106. ThreadSafeArenaStatsHandle& operator=(
  107. ThreadSafeArenaStatsHandle&& other
  108. ) noexcept
  109. {
  110. if (PROTOBUF_PREDICT_FALSE(info_ != nullptr))
  111. {
  112. UnsampleSlow(info_);
  113. }
  114. info_ = absl::exchange(other.info_, nullptr);
  115. return *this;
  116. }
  117. void RecordReset()
  118. {
  119. if (PROTOBUF_PREDICT_TRUE(info_ == nullptr))
  120. return;
  121. RecordResetSlow(info_);
  122. }
  123. ThreadSafeArenaStats* MutableStats()
  124. {
  125. return info_;
  126. }
  127. friend void swap(ThreadSafeArenaStatsHandle& lhs, ThreadSafeArenaStatsHandle& rhs)
  128. {
  129. std::swap(lhs.info_, rhs.info_);
  130. }
  131. friend class ThreadSafeArenaStatsHandlePeer;
  132. private:
  133. ThreadSafeArenaStats* info_ = nullptr;
  134. };
  135. using ThreadSafeArenazSampler =
  136. ::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>;
  137. extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample;
  138. // Returns an RAII sampling handle that manages registration and unregistation
  139. // with the global sampler.
  140. inline ThreadSafeArenaStatsHandle Sample()
  141. {
  142. if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0))
  143. {
  144. return ThreadSafeArenaStatsHandle(nullptr);
  145. }
  146. return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample));
  147. }
  148. #else
  149. struct ThreadSafeArenaStats
  150. {
  151. static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/, size_t /*allocated*/, size_t /*wasted*/)
  152. {
  153. }
  154. };
  155. ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
  156. void UnsampleSlow(ThreadSafeArenaStats* info);
  157. class ThreadSafeArenaStatsHandle
  158. {
  159. public:
  160. explicit ThreadSafeArenaStatsHandle() = default;
  161. explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*)
  162. {
  163. }
  164. void RecordReset()
  165. {
  166. }
  167. ThreadSafeArenaStats* MutableStats()
  168. {
  169. return nullptr;
  170. }
  171. friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&)
  172. {
  173. }
  174. private:
  175. friend class ThreadSafeArenaStatsHandlePeer;
  176. };
  177. class ThreadSafeArenazSampler
  178. {
  179. public:
  180. void Unregister(ThreadSafeArenaStats*)
  181. {
  182. }
  183. void SetMaxSamples(int32_t)
  184. {
  185. }
  186. };
  187. // Returns an RAII sampling handle that manages registration and unregistation
  188. // with the global sampler.
  189. inline ThreadSafeArenaStatsHandle Sample()
  190. {
  191. return ThreadSafeArenaStatsHandle(nullptr);
  192. }
  193. #endif // defined(PROTOBUF_ARENAZ_SAMPLE)
  194. // Returns a global Sampler.
  195. ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler();
  196. // Enables or disables sampling for thread safe arenas.
  197. void SetThreadSafeArenazEnabled(bool enabled);
  198. // Sets the rate at which thread safe arena will be sampled.
  199. void SetThreadSafeArenazSampleParameter(int32_t rate);
  200. // Sets a soft max for the number of samples that will be kept.
  201. void SetThreadSafeArenazMaxSamples(int32_t max);
  202. // Sets the current value for when arenas should be next sampled.
  203. void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
  204. } // namespace internal
  205. } // namespace protobuf
  206. } // namespace google
  207. #include <google/protobuf/port_undef.inc>
  208. #endif // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__