Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(441)

Side by Side Diff: src/counters.h

Issue 2918703002: Localize counter class member functions. (Closed)
Patch Set: Remove need for mutex to initialize counters. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/api.cc ('k') | src/counters.cc » ('j') | src/counters.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_COUNTERS_H_ 5 #ifndef V8_COUNTERS_H_
6 #define V8_COUNTERS_H_ 6 #define V8_COUNTERS_H_
7 7
8 #include "include/v8.h" 8 #include "include/v8.h"
9 #include "src/allocation.h" 9 #include "src/allocation.h"
10 #include "src/base/atomic-utils.h" 10 #include "src/base/atomic-utils.h"
(...skipping 18 matching lines...) Expand all
29 29
30 class StatsTable { 30 class StatsTable {
31 public: 31 public:
32 // Register an application-defined function where 32 // Register an application-defined function where
33 // counters can be looked up. Note: Must be called on main thread, 33 // counters can be looked up. Note: Must be called on main thread,
34 // so that threaded stats counters can be created now. 34 // so that threaded stats counters can be created now.
35 void SetCounterFunction(CounterLookupCallback f); 35 void SetCounterFunction(CounterLookupCallback f);
36 36
37 // Register an application-defined function to create 37 // Register an application-defined function to create
38 // a histogram for passing to the AddHistogramSample function 38 // a histogram for passing to the AddHistogramSample function
39 void SetCreateHistogramFunction(CreateHistogramCallback f) { 39 void SetCreateHistogramFunction(CreateHistogramCallback f);
40 create_histogram_function_ = f;
41 }
42 40
43 // Register an application-defined function to add a sample 41 // Register an application-defined function to add a sample
44 // to a histogram created with CreateHistogram function 42 // to a histogram created with CreateHistogram function
45 void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) { 43 void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
46 add_histogram_sample_function_ = f; 44 add_histogram_sample_function_ = f;
47 } 45 }
48 46
49 bool HasCounterFunction() const { 47 bool HasCounterFunction() const {
50 return lookup_function_ != NULL; 48 return lookup_function_ != NULL;
51 } 49 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 int* FindLocationInStatsTable() const; 112 int* FindLocationInStatsTable() const;
115 }; 113 };
116 114
117 // StatsCounters are dynamically created values which can be tracked in 115 // StatsCounters are dynamically created values which can be tracked in
118 // the StatsTable. They are designed to be lightweight to create and 116 // the StatsTable. They are designed to be lightweight to create and
119 // easy to use. 117 // easy to use.
120 // 118 //
121 // Internally, a counter represents a value in a row of a StatsTable. 119 // Internally, a counter represents a value in a row of a StatsTable.
122 // The row has a 32bit value for each process/thread in the table and also 120 // The row has a 32bit value for each process/thread in the table and also
123 // a name (stored in the table metadata). Since the storage location can be 121 // a name (stored in the table metadata). Since the storage location can be
124 // thread-specific, this class cannot be shared across threads. 122 // thread-specific, this class cannot be shared across threads. Note: This
123 // class is not thread safe.
125 class StatsCounter : public StatsCounterBase { 124 class StatsCounter : public StatsCounterBase {
126 public: 125 public:
127 StatsCounter() { }
128 StatsCounter(Counters* counters, const char* name)
129 : StatsCounterBase(counters, name), lookup_done_(false) {}
130
131 // Sets the counter to a specific value. 126 // Sets the counter to a specific value.
132 void Set(int value) { 127 void Set(int value) {
133 if (int* loc = GetPtr()) SetLoc(loc, value); 128 if (int* loc = GetPtr()) SetLoc(loc, value);
134 } 129 }
135 130
136 // Increments the counter. 131 // Increments the counter.
137 void Increment() { 132 void Increment() {
138 if (int* loc = GetPtr()) IncrementLoc(loc); 133 if (int* loc = GetPtr()) IncrementLoc(loc);
139 } 134 }
140 135
(...skipping 18 matching lines...) Expand all
159 154
160 // Get the internal pointer to the counter. This is used 155 // Get the internal pointer to the counter. This is used
161 // by the code generator to emit code that manipulates a 156 // by the code generator to emit code that manipulates a
162 // given counter without calling the runtime system. 157 // given counter without calling the runtime system.
163 int* GetInternalPointer() { 158 int* GetInternalPointer() {
164 int* loc = GetPtr(); 159 int* loc = GetPtr();
165 DCHECK(loc != NULL); 160 DCHECK(loc != NULL);
166 return loc; 161 return loc;
167 } 162 }
168 163
164 private:
165 StatsCounter() {}
166 StatsCounter(Counters* counters, const char* name)
167 : StatsCounterBase(counters, name), lookup_done_(false) {}
169 // Reset the cached internal pointer. 168 // Reset the cached internal pointer.
170 void Reset() { lookup_done_ = false; } 169 void Reset() { lookup_done_ = false; }
171 170
172 private:
173 // Returns the cached address of this counter location. 171 // Returns the cached address of this counter location.
174 int* GetPtr() { 172 int* GetPtr() {
175 if (lookup_done_) return ptr_; 173 if (lookup_done_) return ptr_;
176 lookup_done_ = true; 174 lookup_done_ = true;
177 ptr_ = FindLocationInStatsTable(); 175 ptr_ = FindLocationInStatsTable();
178 return ptr_; 176 return ptr_;
179 } 177 }
180 178
181 bool lookup_done_; 179 bool lookup_done_;
180
181 friend class Counters;
182 }; 182 };
183 183
184 // Thread safe version of StatsCounter. WARNING: Unlike StatsCounter, 184 // Thread safe version of StatsCounter.
185 // StatsCounterThreadSafe's constructor and method Reset() actually do
186 // the table lookup, and should be called from the main thread
187 // (i.e. not workers).
188 class StatsCounterThreadSafe : public StatsCounterBase { 185 class StatsCounterThreadSafe : public StatsCounterBase {
189 public: 186 public:
190 StatsCounterThreadSafe(Counters* counters, const char* name);
191
192 void Set(int Value); 187 void Set(int Value);
193 void Increment(); 188 void Increment();
194 void Increment(int value); 189 void Increment(int value);
195 void Decrement(); 190 void Decrement();
196 void Decrement(int value); 191 void Decrement(int value);
197 bool Enabled() { return ptr_ != NULL; } 192 bool Enabled() { return ptr_ != NULL; }
198 int* GetInternalPointer() { 193 int* GetInternalPointer() {
199 DCHECK(ptr_ != NULL); 194 DCHECK(ptr_ != NULL);
200 return ptr_; 195 return ptr_;
201 } 196 }
202 void Reset() { GetPtr(); }
203 197
204 private: 198 private:
199 StatsCounterThreadSafe(Counters* counters, const char* name);
205 int* GetPtr(); 200 int* GetPtr();
Mircea Trofin 2017/06/05 15:57:49 Why not delete GetPtr(), since it's only used in R
kschimpf 2017/06/05 17:38:52 Your right. It used to have multiple uses, but is
201 void Reset() { GetPtr(); }
206 202
207 base::Mutex mutex_; 203 base::Mutex mutex_;
208 204
209 private: 205 private:
206 friend class Counters;
210 DISALLOW_IMPLICIT_CONSTRUCTORS(StatsCounterThreadSafe); 207 DISALLOW_IMPLICIT_CONSTRUCTORS(StatsCounterThreadSafe);
211 }; 208 };
212 209
213 // A Histogram represents a dynamically created histogram in the StatsTable. 210 // A Histogram represents a dynamically created histogram in the
214 // It will be registered with the histogram system on first use. 211 // StatsTable. Note: This class is thread safe.
215 class Histogram { 212 class Histogram {
216 public: 213 public:
217 Histogram() { } 214 // Add a single sample to this histogram.
215 void AddSample(int sample);
216
217 // Returns true if this histogram is enabled.
218 bool Enabled() { return histogram_ != nullptr; }
219
220 const char* name() { return name_; }
221
222 protected:
223 Counters* counters() const { return counters_; }
224
225 protected:
226 Histogram() {}
218 Histogram(const char* name, int min, int max, int num_buckets, 227 Histogram(const char* name, int min, int max, int num_buckets,
219 Counters* counters) 228 Counters* counters)
220 : name_(name), 229 : name_(name),
221 min_(min), 230 min_(min),
222 max_(max), 231 max_(max),
223 num_buckets_(num_buckets), 232 num_buckets_(num_buckets),
224 histogram_(NULL), 233 histogram_(nullptr),
225 lookup_done_(false),
226 counters_(counters) {} 234 counters_(counters) {}
227 235
228 // Add a single sample to this histogram.
229 void AddSample(int sample);
230
231 // Returns true if this histogram is enabled.
232 bool Enabled() {
233 return GetHistogram() != NULL;
234 }
235
236 // Reset the cached internal pointer. 236 // Reset the cached internal pointer.
237 void Reset() { 237 void Reset() { histogram_ = CreateHistogram(); }
238 lookup_done_ = false;
239 }
240
241 const char* name() { return name_; }
242
243 protected:
244 // Returns the handle to the histogram.
245 void* GetHistogram() {
246 if (!lookup_done_) {
247 lookup_done_ = true;
248 histogram_ = CreateHistogram();
249 }
250 return histogram_;
251 }
252
253 Counters* counters() const { return counters_; }
254 238
255 private: 239 private:
256 void* CreateHistogram() const; 240 void* CreateHistogram() const;
257 241
258 const char* name_; 242 const char* name_;
259 int min_; 243 int min_;
260 int max_; 244 int max_;
261 int num_buckets_; 245 int num_buckets_;
262 void* histogram_; 246 void* histogram_;
263 bool lookup_done_;
264 Counters* counters_; 247 Counters* counters_;
248
249 friend class Counters;
265 }; 250 };
266 251
267 // A HistogramTimer allows distributions of results to be created. 252 // A HistogramTimer allows distributions of results to be created.
268 class HistogramTimer : public Histogram { 253 class HistogramTimer : public Histogram {
269 public: 254 public:
270 enum Resolution { 255 enum Resolution {
271 MILLISECOND, 256 MILLISECOND,
272 MICROSECOND 257 MICROSECOND
273 }; 258 };
274 259
275 HistogramTimer() {} 260 // Note: public for testing purposes only.
276 HistogramTimer(const char* name, int min, int max, Resolution resolution, 261 HistogramTimer(const char* name, int min, int max, Resolution resolution,
277 int num_buckets, Counters* counters) 262 int num_buckets, Counters* counters)
278 : Histogram(name, min, max, num_buckets, counters), 263 : Histogram(name, min, max, num_buckets, counters),
279 resolution_(resolution) {} 264 resolution_(resolution) {}
280 265
281 // Start the timer. 266 // Start the timer.
282 void Start(); 267 void Start();
283 268
284 // Stop the timer and record the results. 269 // Stop the timer and record the results.
285 void Stop(); 270 void Stop();
286 271
287 // Returns true if the timer is running. 272 // Returns true if the timer is running.
288 bool Running() { 273 bool Running() {
289 return Enabled() && timer_.IsStarted(); 274 return Enabled() && timer_.IsStarted();
290 } 275 }
291 276
292 // TODO(bmeurer): Remove this when HistogramTimerScope is fixed. 277 // TODO(bmeurer): Remove this when HistogramTimerScope is fixed.
293 #ifdef DEBUG 278 #ifdef DEBUG
294 base::ElapsedTimer* timer() { return &timer_; } 279 base::ElapsedTimer* timer() { return &timer_; }
295 #endif 280 #endif
296 281
297 private: 282 private:
283 HistogramTimer() {}
284
298 base::ElapsedTimer timer_; 285 base::ElapsedTimer timer_;
299 Resolution resolution_; 286 Resolution resolution_;
287
288 friend class Counters;
300 }; 289 };
301 290
302 // Helper class for scoping a HistogramTimer. 291 // Helper class for scoping a HistogramTimer.
303 // TODO(bmeurer): The ifdeffery is an ugly hack around the fact that the 292 // TODO(bmeurer): The ifdeffery is an ugly hack around the fact that the
304 // Parser is currently reentrant (when it throws an error, we call back 293 // Parser is currently reentrant (when it throws an error, we call back
305 // into JavaScript and all bets are off), but ElapsedTimer is not 294 // into JavaScript and all bets are off), but ElapsedTimer is not
306 // reentry-safe. Fix this properly and remove |allow_nesting|. 295 // reentry-safe. Fix this properly and remove |allow_nesting|.
307 class HistogramTimerScope BASE_EMBEDDED { 296 class HistogramTimerScope BASE_EMBEDDED {
308 public: 297 public:
309 explicit HistogramTimerScope(HistogramTimer* timer, 298 explicit HistogramTimerScope(HistogramTimer* timer,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // An example use might be to aggregate the time spent in lazy compilation 337 // An example use might be to aggregate the time spent in lazy compilation
349 // while running a script. 338 // while running a script.
350 // 339 //
351 // Helpers: 340 // Helpers:
352 // - AggregatingHistogramTimerScope, the "outer" scope within which 341 // - AggregatingHistogramTimerScope, the "outer" scope within which
353 // times will be summed up. 342 // times will be summed up.
354 // - AggregatedHistogramTimerScope, the "inner" scope which defines the 343 // - AggregatedHistogramTimerScope, the "inner" scope which defines the
355 // events to be timed. 344 // events to be timed.
356 class AggregatableHistogramTimer : public Histogram { 345 class AggregatableHistogramTimer : public Histogram {
357 public: 346 public:
358 AggregatableHistogramTimer() {}
359 AggregatableHistogramTimer(const char* name, int min, int max,
360 int num_buckets, Counters* counters)
361 : Histogram(name, min, max, num_buckets, counters) {}
362
363 // Start/stop the "outer" scope. 347 // Start/stop the "outer" scope.
364 void Start() { time_ = base::TimeDelta(); } 348 void Start() { time_ = base::TimeDelta(); }
365 void Stop() { AddSample(static_cast<int>(time_.InMicroseconds())); } 349 void Stop() { AddSample(static_cast<int>(time_.InMicroseconds())); }
366 350
367 // Add a time value ("inner" scope). 351 // Add a time value ("inner" scope).
368 void Add(base::TimeDelta other) { time_ += other; } 352 void Add(base::TimeDelta other) { time_ += other; }
369 353
370 private: 354 private:
355 AggregatableHistogramTimer() {}
356 AggregatableHistogramTimer(const char* name, int min, int max,
357 int num_buckets, Counters* counters)
358 : Histogram(name, min, max, num_buckets, counters) {}
359
371 base::TimeDelta time_; 360 base::TimeDelta time_;
361 friend class Counters;
372 }; 362 };
373 363
374 // A helper class for use with AggregatableHistogramTimer. This is the 364 // A helper class for use with AggregatableHistogramTimer. This is the
375 // // outer-most timer scope used with an AggregatableHistogramTimer. It will 365 // // outer-most timer scope used with an AggregatableHistogramTimer. It will
376 // // aggregate the information from the inner AggregatedHistogramTimerScope. 366 // // aggregate the information from the inner AggregatedHistogramTimerScope.
377 class AggregatingHistogramTimerScope { 367 class AggregatingHistogramTimerScope {
378 public: 368 public:
379 explicit AggregatingHistogramTimerScope(AggregatableHistogramTimer* histogram) 369 explicit AggregatingHistogramTimerScope(AggregatableHistogramTimer* histogram)
380 : histogram_(histogram) { 370 : histogram_(histogram) {
381 histogram_->Start(); 371 histogram_->Start();
(...skipping 25 matching lines...) Expand all
407 // backing histogram receives one sample every T ms, where the T is controlled 397 // backing histogram receives one sample every T ms, where the T is controlled
408 // by the FLAG_histogram_interval. 398 // by the FLAG_histogram_interval.
409 // 399 //
410 // More formally: let F be a real-valued function that maps time to sample 400 // More formally: let F be a real-valued function that maps time to sample
411 // values. We define F as a linear interpolation between adjacent samples. For 401 // values. We define F as a linear interpolation between adjacent samples. For
412 // each time interval [x; x + T) the backing histogram gets one sample value 402 // each time interval [x; x + T) the backing histogram gets one sample value
413 // that is the average of F(t) in the interval. 403 // that is the average of F(t) in the interval.
414 template <typename Histogram> 404 template <typename Histogram>
415 class AggregatedMemoryHistogram { 405 class AggregatedMemoryHistogram {
416 public: 406 public:
417 AggregatedMemoryHistogram() 407 // Note: public for testing purposes only.
418 : is_initialized_(false),
419 start_ms_(0.0),
420 last_ms_(0.0),
421 aggregate_value_(0.0),
422 last_value_(0.0),
423 backing_histogram_(NULL) {}
424
425 explicit AggregatedMemoryHistogram(Histogram* backing_histogram) 408 explicit AggregatedMemoryHistogram(Histogram* backing_histogram)
426 : AggregatedMemoryHistogram() { 409 : AggregatedMemoryHistogram() {
427 backing_histogram_ = backing_histogram; 410 backing_histogram_ = backing_histogram;
428 } 411 }
429 412
430 // Invariants that hold before and after AddSample if 413 // Invariants that hold before and after AddSample if
431 // is_initialized_ is true: 414 // is_initialized_ is true:
432 // 415 //
433 // 1) For we processed samples that came in before start_ms_ and sent the 416 // 1) For we processed samples that came in before start_ms_ and sent the
434 // corresponding aggregated samples to backing histogram. 417 // corresponding aggregated samples to backing histogram.
435 // 2) (last_ms_, last_value_) is the last received sample. 418 // 2) (last_ms_, last_value_) is the last received sample.
436 // 3) last_ms_ < start_ms_ + FLAG_histogram_interval. 419 // 3) last_ms_ < start_ms_ + FLAG_histogram_interval.
437 // 4) aggregate_value_ is the average of the function that is constructed by 420 // 4) aggregate_value_ is the average of the function that is constructed by
438 // linearly interpolating samples received between start_ms_ and last_ms_. 421 // linearly interpolating samples received between start_ms_ and last_ms_.
439 void AddSample(double current_ms, double current_value); 422 void AddSample(double current_ms, double current_value);
440 423
441 private: 424 private:
425 AggregatedMemoryHistogram()
426 : is_initialized_(false),
427 start_ms_(0.0),
428 last_ms_(0.0),
429 aggregate_value_(0.0),
430 last_value_(0.0),
431 backing_histogram_(NULL) {}
432
442 double Aggregate(double current_ms, double current_value); 433 double Aggregate(double current_ms, double current_value);
443 bool is_initialized_; 434 bool is_initialized_;
444 double start_ms_; 435 double start_ms_;
445 double last_ms_; 436 double last_ms_;
446 double aggregate_value_; 437 double aggregate_value_;
447 double last_value_; 438 double last_value_;
448 Histogram* backing_histogram_; 439 Histogram* backing_histogram_;
440
441 friend class Counters;
449 }; 442 };
450 443
451 444
452 template <typename Histogram> 445 template <typename Histogram>
453 void AggregatedMemoryHistogram<Histogram>::AddSample(double current_ms, 446 void AggregatedMemoryHistogram<Histogram>::AddSample(double current_ms,
454 double current_value) { 447 double current_value) {
455 if (!is_initialized_) { 448 if (!is_initialized_) {
456 aggregate_value_ = current_value; 449 aggregate_value_ = current_value;
457 start_ms_ = current_ms; 450 start_ms_ = current_ms;
458 last_value_ = current_value; 451 last_value_ = current_value;
(...skipping 864 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COUNTER_ID) 1316 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(COUNTER_ID)
1324 #undef COUNTER_ID 1317 #undef COUNTER_ID
1325 #define COUNTER_ID(name) kCountOfCODE_AGE__##name, \ 1318 #define COUNTER_ID(name) kCountOfCODE_AGE__##name, \
1326 kSizeOfCODE_AGE__##name, 1319 kSizeOfCODE_AGE__##name,
1327 CODE_AGE_LIST_COMPLETE(COUNTER_ID) 1320 CODE_AGE_LIST_COMPLETE(COUNTER_ID)
1328 #undef COUNTER_ID 1321 #undef COUNTER_ID
1329 stats_counter_count 1322 stats_counter_count
1330 }; 1323 };
1331 // clang-format on 1324 // clang-format on
1332 1325
1333 void ResetCounters();
1334 void ResetHistograms();
1335 void InitializeHistograms();
1336
1337 RuntimeCallStats* runtime_call_stats() { return &runtime_call_stats_; } 1326 RuntimeCallStats* runtime_call_stats() { return &runtime_call_stats_; }
1338 1327
1339 StatsTable* stats_table() { return &stats_table_; } 1328 StatsTable* stats_table() { return &stats_table_; }
1340 1329
1341 Isolate* isolate() { return isolate_; } 1330 Isolate* isolate() { return isolate_; }
1342 1331
1343 private: 1332 private:
1344 Isolate* isolate_; 1333 Isolate* isolate_;
1345 StatsTable stats_table_; 1334 StatsTable stats_table_;
1346 1335
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 #undef SC 1391 #undef SC
1403 1392
1404 #define SC(name) \ 1393 #define SC(name) \
1405 StatsCounter size_of_CODE_AGE_##name##_; \ 1394 StatsCounter size_of_CODE_AGE_##name##_; \
1406 StatsCounter count_of_CODE_AGE_##name##_; 1395 StatsCounter count_of_CODE_AGE_##name##_;
1407 CODE_AGE_LIST_COMPLETE(SC) 1396 CODE_AGE_LIST_COMPLETE(SC)
1408 #undef SC 1397 #undef SC
1409 1398
1410 RuntimeCallStats runtime_call_stats_; 1399 RuntimeCallStats runtime_call_stats_;
1411 1400
1401 friend class StatsTable;
1402 void ResetCounters();
1403 void ResetHistograms();
1404
1412 DISALLOW_IMPLICIT_CONSTRUCTORS(Counters); 1405 DISALLOW_IMPLICIT_CONSTRUCTORS(Counters);
1413 }; 1406 };
1414 1407
1415 } // namespace internal 1408 } // namespace internal
1416 } // namespace v8 1409 } // namespace v8
1417 1410
1418 #endif // V8_COUNTERS_H_ 1411 #endif // V8_COUNTERS_H_
OLDNEW
« no previous file with comments | « src/api.cc ('k') | src/counters.cc » ('j') | src/counters.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698