blob: 233837635a411261d051f17c4a77b5e40a7e20dd [file] [log] [blame]
jkummerow@chromium.org28583c92012-07-16 11:31:55 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_COUNTERS_H_
29#define V8_COUNTERS_H_
30
whesse@chromium.org023421e2010-12-21 12:19:12 +000031#include "../include/v8.h"
32#include "allocation.h"
33
kasperl@chromium.org71affb52009-05-26 05:44:31 +000034namespace v8 {
35namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37// StatsCounters is an interface for plugging into external
38// counters for monitoring. Counters can be looked up and
39// manipulated by name.
40
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000041class StatsTable {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000042 public:
43 // Register an application-defined function where
44 // counters can be looked up.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000045 void SetCounterFunction(CounterLookupCallback f) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046 lookup_function_ = f;
47 }
48
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000049 // Register an application-defined function to create
50 // a histogram for passing to the AddHistogramSample function
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000051 void SetCreateHistogramFunction(CreateHistogramCallback f) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000052 create_histogram_function_ = f;
53 }
54
55 // Register an application-defined function to add a sample
56 // to a histogram created with CreateHistogram function
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000057 void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000058 add_histogram_sample_function_ = f;
59 }
60
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000061 bool HasCounterFunction() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062 return lookup_function_ != NULL;
63 }
64
65 // Lookup the location of a counter by name. If the lookup
66 // is successful, returns a non-NULL pointer for writing the
67 // value of the counter. Each thread calling this function
68 // may receive a different location to store it's counter.
69 // The return value must not be cached and re-used across
70 // threads, although a single thread is free to cache it.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000071 int* FindLocation(const char* name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000072 if (!lookup_function_) return NULL;
73 return lookup_function_(name);
74 }
75
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000076 // Create a histogram by name. If the create is successful,
77 // returns a non-NULL pointer for use with AddHistogramSample
78 // function. min and max define the expected minimum and maximum
79 // sample values. buckets is the maximum number of buckets
80 // that the samples will be grouped into.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000081 void* CreateHistogram(const char* name,
82 int min,
83 int max,
84 size_t buckets) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000085 if (!create_histogram_function_) return NULL;
86 return create_histogram_function_(name, min, max, buckets);
87 }
88
89 // Add a sample to a histogram created with the CreateHistogram
90 // function.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000091 void AddHistogramSample(void* histogram, int sample) {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000092 if (!add_histogram_sample_function_) return;
93 return add_histogram_sample_function_(histogram, sample);
94 }
95
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000097 StatsTable();
98
99 CounterLookupCallback lookup_function_;
100 CreateHistogramCallback create_histogram_function_;
101 AddHistogramSampleCallback add_histogram_sample_function_;
102
103 friend class Isolate;
104
105 DISALLOW_COPY_AND_ASSIGN(StatsTable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106};
107
108// StatsCounters are dynamically created values which can be tracked in
109// the StatsTable. They are designed to be lightweight to create and
110// easy to use.
111//
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112// Internally, a counter represents a value in a row of a StatsTable.
113// The row has a 32bit value for each process/thread in the table and also
114// a name (stored in the table metadata). Since the storage location can be
115// thread-specific, this class cannot be shared across threads.
116//
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000117// This class is designed to be POD initialized. It will be registered with
118// the counter system on first use. For example:
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000119// StatsCounter c = { "c:myctr", NULL, false };
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000120struct StatsCounter {
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000121 const char* name_;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000122 int* ptr_;
123 bool lookup_done_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124
125 // Sets the counter to a specific value.
126 void Set(int value) {
127 int* loc = GetPtr();
128 if (loc) *loc = value;
129 }
130
131 // Increments the counter.
132 void Increment() {
133 int* loc = GetPtr();
134 if (loc) (*loc)++;
135 }
136
137 void Increment(int value) {
138 int* loc = GetPtr();
139 if (loc)
140 (*loc) += value;
141 }
142
143 // Decrements the counter.
144 void Decrement() {
145 int* loc = GetPtr();
146 if (loc) (*loc)--;
147 }
148
149 void Decrement(int value) {
150 int* loc = GetPtr();
151 if (loc) (*loc) -= value;
152 }
153
154 // Is this counter enabled?
155 // Returns false if table is full.
156 bool Enabled() {
157 return GetPtr() != NULL;
158 }
159
160 // Get the internal pointer to the counter. This is used
161 // by the code generator to emit code that manipulates a
162 // given counter without calling the runtime system.
163 int* GetInternalPointer() {
164 int* loc = GetPtr();
165 ASSERT(loc != NULL);
166 return loc;
167 }
168
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 protected:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000170 // Returns the cached address of this counter location.
171 int* GetPtr() {
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000172 if (lookup_done_) return ptr_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000173 lookup_done_ = true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000174 ptr_ = FindLocationInStatsTable();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000175 return ptr_;
176 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000177
178 private:
179 int* FindLocationInStatsTable() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000180};
181
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000182// StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 };
183struct StatsCounterTimer {
184 StatsCounter counter_;
185
186 int64_t start_time_;
187 int64_t stop_time_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188
189 // Start the timer.
190 void Start();
191
192 // Stop the timer and record the results.
193 void Stop();
194
195 // Returns true if the timer is running.
196 bool Running() {
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000197 return counter_.Enabled() && start_time_ != 0 && stop_time_ == 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000198 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199};
200
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000201// A Histogram represents a dynamically created histogram in the StatsTable.
202//
203// This class is designed to be POD initialized. It will be registered with
204// the histogram system on first use. For example:
205// Histogram h = { "myhist", 0, 10000, 50, NULL, false };
206struct Histogram {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000207 const char* name_;
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000208 int min_;
209 int max_;
210 int num_buckets_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000211 void* histogram_;
212 bool lookup_done_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000213
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000214 // Add a single sample to this histogram.
215 void AddSample(int sample);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000216
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000217 // Returns true if this histogram is enabled.
218 bool Enabled() {
219 return GetHistogram() != NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000220 }
221
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000222 protected:
223 // Returns the handle to the histogram.
224 void* GetHistogram() {
225 if (!lookup_done_) {
226 lookup_done_ = true;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000227 histogram_ = CreateHistogram();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000229 return histogram_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000231
232 private:
233 void* CreateHistogram() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234};
235
jkummerow@chromium.org28583c92012-07-16 11:31:55 +0000236// A HistogramTimer allows distributions of results to be created
237// HistogramTimer t = { {L"foo", 0, 10000, 50, NULL, false}, 0, 0 };
238struct HistogramTimer {
239 Histogram histogram_;
240
241 int64_t start_time_;
242 int64_t stop_time_;
243
244 // Start the timer.
245 void Start();
246
247 // Stop the timer and record the results.
248 void Stop();
249
250 // Returns true if the timer is running.
251 bool Running() {
252 return histogram_.Enabled() && (start_time_ != 0) && (stop_time_ == 0);
253 }
254};
255
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000256// Helper class for scoping a HistogramTimer.
257class HistogramTimerScope BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000258 public:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000259 explicit HistogramTimerScope(HistogramTimer* timer) :
260 timer_(timer) {
261 timer_->Start();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000262 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000263 ~HistogramTimerScope() {
264 timer_->Stop();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265 }
266 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000267 HistogramTimer* timer_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000268};
269
270
271} } // namespace v8::internal
272
273#endif // V8_COUNTERS_H_