Coverage Report

Created: 2023-03-26 07:54

/src/LPM/external.protobuf/include/google/protobuf/arenaz_sampler.h
Line
Count
Source (jump to first uncovered line)
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
31
#ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
32
#define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
33
34
#include <atomic>
35
#include <cstddef>
36
#include <cstdint>
37
38
39
// Must be included last.
40
#include <google/protobuf/port_def.inc>
41
42
namespace google {
43
namespace protobuf {
44
namespace internal {
45
46
#if defined(PROTOBUF_ARENAZ_SAMPLE)
47
struct ThreadSafeArenaStats;
48
void RecordResetSlow(ThreadSafeArenaStats* info);
49
void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested,
50
                        size_t allocated, size_t wasted);
51
// Stores information about a sampled thread safe arena.  All mutations to this
52
// *must* be made through `Record*` functions below.  All reads from this *must*
53
// only occur in the callback to `ThreadSafeArenazSampler::Iterate`.
54
struct ThreadSafeArenaStats
55
    : public absl::profiling_internal::Sample<ThreadSafeArenaStats> {
56
  // Constructs the object but does not fill in any fields.
57
  ThreadSafeArenaStats();
58
  ~ThreadSafeArenaStats();
59
60
  // Puts the object into a clean state, fills in the logically `const` members,
61
  // blocking for any readers that are currently sampling the object.
62
  void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
63
64
  // These fields are mutated by the various Record* APIs and need to be
65
  // thread-safe.
66
  std::atomic<int> num_allocations;
67
  std::atomic<int> num_resets;
68
  std::atomic<size_t> bytes_requested;
69
  std::atomic<size_t> bytes_allocated;
70
  std::atomic<size_t> bytes_wasted;
71
  // Records the largest size an arena ever had.  Maintained across resets.
72
  std::atomic<size_t> max_bytes_allocated;
73
  // Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the
74
  // underlying arena.  The field is maintained across resets.
75
  std::atomic<uint64_t> thread_ids;
76
77
  // All of the fields below are set by `PrepareForSampling`, they must not
78
  // be mutated in `Record*` functions.  They are logically `const` in that
79
  // sense. These are guarded by init_mu, but that is not externalized to
80
  // clients, who can only read them during
81
  // `ThreadSafeArenazSampler::Iterate` which will hold the lock.
82
  static constexpr int kMaxStackDepth = 64;
83
  int32_t depth;
84
  void* stack[kMaxStackDepth];
85
  static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested,
86
                                  size_t allocated, size_t wasted) {
87
    if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return;
88
    RecordAllocateSlow(info, requested, allocated, wasted);
89
  }
90
};
91
92
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
93
void UnsampleSlow(ThreadSafeArenaStats* info);
94
95
class ThreadSafeArenaStatsHandle {
96
 public:
97
  explicit ThreadSafeArenaStatsHandle() = default;
98
  explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats* info)
99
      : info_(info) {}
100
101
  ~ThreadSafeArenaStatsHandle() {
102
    if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
103
    UnsampleSlow(info_);
104
  }
105
106
  ThreadSafeArenaStatsHandle(ThreadSafeArenaStatsHandle&& other) noexcept
107
      : info_(absl::exchange(other.info_, nullptr)) {}
108
109
  ThreadSafeArenaStatsHandle& operator=(
110
      ThreadSafeArenaStatsHandle&& other) noexcept {
111
    if (PROTOBUF_PREDICT_FALSE(info_ != nullptr)) {
112
      UnsampleSlow(info_);
113
    }
114
    info_ = absl::exchange(other.info_, nullptr);
115
    return *this;
116
  }
117
118
  void RecordReset() {
119
    if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
120
    RecordResetSlow(info_);
121
  }
122
123
  ThreadSafeArenaStats* MutableStats() { return info_; }
124
125
  friend void swap(ThreadSafeArenaStatsHandle& lhs,
126
                   ThreadSafeArenaStatsHandle& rhs) {
127
    std::swap(lhs.info_, rhs.info_);
128
  }
129
130
  friend class ThreadSafeArenaStatsHandlePeer;
131
132
 private:
133
  ThreadSafeArenaStats* info_ = nullptr;
134
};
135
136
using ThreadSafeArenazSampler =
137
    ::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>;
138
139
extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample;
140
141
// Returns an RAII sampling handle that manages registration and unregistation
142
// with the global sampler.
143
inline ThreadSafeArenaStatsHandle Sample() {
144
  if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) {
145
    return ThreadSafeArenaStatsHandle(nullptr);
146
  }
147
  return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample));
148
}
149
150
#else
151
struct ThreadSafeArenaStats {
152
  static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/,
153
0
                                  size_t /*allocated*/, size_t /*wasted*/) {}
154
};
155
156
ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
157
void UnsampleSlow(ThreadSafeArenaStats* info);
158
159
class ThreadSafeArenaStatsHandle {
160
 public:
161
  explicit ThreadSafeArenaStatsHandle() = default;
162
0
  explicit ThreadSafeArenaStatsHandle(ThreadSafeArenaStats*) {}
163
164
0
  void RecordReset() {}
165
166
0
  ThreadSafeArenaStats* MutableStats() { return nullptr; }
167
168
0
  friend void swap(ThreadSafeArenaStatsHandle&, ThreadSafeArenaStatsHandle&) {}
169
170
 private:
171
  friend class ThreadSafeArenaStatsHandlePeer;
172
};
173
174
class ThreadSafeArenazSampler {
175
 public:
176
0
  void Unregister(ThreadSafeArenaStats*) {}
177
0
  void SetMaxSamples(int32_t) {}
178
};
179
180
// Returns an RAII sampling handle that manages registration and unregistation
181
// with the global sampler.
182
0
inline ThreadSafeArenaStatsHandle Sample() {
183
0
  return ThreadSafeArenaStatsHandle(nullptr);
184
0
}
185
#endif  // defined(PROTOBUF_ARENAZ_SAMPLE)
186
187
// Returns a global Sampler.
188
ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler();
189
190
// Enables or disables sampling for thread safe arenas.
191
void SetThreadSafeArenazEnabled(bool enabled);
192
193
// Sets the rate at which thread safe arena will be sampled.
194
void SetThreadSafeArenazSampleParameter(int32_t rate);
195
196
// Sets a soft max for the number of samples that will be kept.
197
void SetThreadSafeArenazMaxSamples(int32_t max);
198
199
// Sets the current value for when arenas should be next sampled.
200
void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
201
202
}  // namespace internal
203
}  // namespace protobuf
204
}  // namespace google
205
206
#include <google/protobuf/port_undef.inc>
207
#endif  // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__