1// Copyright 2007-2008 the V8 project authors. All rights reserved.
2// 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
31#include "../include/v8.h"
32#include "allocation.h"
33
34namespace v8 {
35namespace internal {
36
37// StatsCounters is an interface for plugging into external
38// counters for monitoring.  Counters can be looked up and
39// manipulated by name.
40
41class StatsTable {
42 public:
43  // Register an application-defined function where
44  // counters can be looked up.
45  void SetCounterFunction(CounterLookupCallback f) {
46    lookup_function_ = f;
47  }
48
49  // Register an application-defined function to create
50  // a histogram for passing to the AddHistogramSample function
51  void SetCreateHistogramFunction(CreateHistogramCallback f) {
52    create_histogram_function_ = f;
53  }
54
55  // Register an application-defined function to add a sample
56  // to a histogram created with CreateHistogram function
57  void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
58    add_histogram_sample_function_ = f;
59  }
60
61  bool HasCounterFunction() const {
62    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.
71  int* FindLocation(const char* name) {
72    if (!lookup_function_) return NULL;
73    return lookup_function_(name);
74  }
75
76  // 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.
81  void* CreateHistogram(const char* name,
82                        int min,
83                        int max,
84                        size_t buckets) {
85    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.
91  void AddHistogramSample(void* histogram, int sample) {
92    if (!add_histogram_sample_function_) return;
93    return add_histogram_sample_function_(histogram, sample);
94  }
95
96 private:
97  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);
106};
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//
112// 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//
117// This class is designed to be POD initialized.  It will be registered with
118// the counter system on first use.  For example:
119//   StatsCounter c = { "c:myctr", NULL, false };
120struct StatsCounter {
121  const char* name_;
122  int* ptr_;
123  bool lookup_done_;
124
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
169 protected:
170  // Returns the cached address of this counter location.
171  int* GetPtr() {
172    if (lookup_done_)
173      return ptr_;
174    lookup_done_ = true;
175    ptr_ = FindLocationInStatsTable();
176    return ptr_;
177  }
178
179 private:
180  int* FindLocationInStatsTable() const;
181};
182
183// StatsCounterTimer t = { { L"t:foo", NULL, false }, 0, 0 };
184struct StatsCounterTimer {
185  StatsCounter counter_;
186
187  int64_t start_time_;
188  int64_t stop_time_;
189
190  // Start the timer.
191  void Start();
192
193  // Stop the timer and record the results.
194  void Stop();
195
196  // Returns true if the timer is running.
197  bool Running() {
198    return counter_.Enabled() && start_time_ != 0 && stop_time_ == 0;
199  }
200};
201
202// A HistogramTimer allows distributions of results to be created
203// HistogramTimer t = { L"foo", NULL, false, 0, 0 };
204struct HistogramTimer {
205  const char* name_;
206  void* histogram_;
207  bool lookup_done_;
208
209  int64_t start_time_;
210  int64_t stop_time_;
211
212  // Start the timer.
213  void Start();
214
215  // Stop the timer and record the results.
216  void Stop();
217
218  // Returns true if the timer is running.
219  bool Running() {
220    return (histogram_ != NULL) && (start_time_ != 0) && (stop_time_ == 0);
221  }
222
223 protected:
224  // Returns the handle to the histogram.
225  void* GetHistogram() {
226    if (!lookup_done_) {
227      lookup_done_ = true;
228      histogram_ = CreateHistogram();
229    }
230    return histogram_;
231  }
232
233 private:
234  void* CreateHistogram() const;
235};
236
237// Helper class for scoping a HistogramTimer.
238class HistogramTimerScope BASE_EMBEDDED {
239 public:
240  explicit HistogramTimerScope(HistogramTimer* timer) :
241  timer_(timer) {
242    timer_->Start();
243  }
244  ~HistogramTimerScope() {
245    timer_->Stop();
246  }
247 private:
248  HistogramTimer* timer_;
249};
250
251
252} }  // namespace v8::internal
253
254#endif  // V8_COUNTERS_H_
255