- Added ability to call histograms from within v8
authordavemoore@chromium.org <davemoore@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Mar 2009 16:06:31 +0000 (16:06 +0000)
committerdavemoore@chromium.org <davemoore@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 13 Mar 2009 16:06:31 +0000 (16:06 +0000)
- Changed the StatsRates to use the new HistogramTimers

Review URL: http://codereview.chromium.org/42020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1510 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
src/api.cc
src/compiler.cc
src/counters.cc
src/counters.h
src/heap.cc
src/parser.cc
src/v8-counters.cc
src/v8-counters.h

index 44d030700295dce394dacc2483cc8b49201c34b1..00fb9957555b80ff69c8b61d414023752337c49b 100644 (file)
@@ -839,7 +839,7 @@ class EXPORT String : public Primitive {
    * external string resource.
    */
   static Local<String> NewExternal(ExternalStringResource* resource);
-  
+
   /**
    * Associate an external string resource with this string by transforming it
    * in place so that existing references to this string in the JavaScript heap
@@ -859,7 +859,7 @@ class EXPORT String : public Primitive {
    * external string resource.
    */
   static Local<String> NewExternal(ExternalAsciiStringResource* resource);
-  
+
   /**
    * Associate an external string resource with this string by transforming it
    * in place so that existing references to this string in the JavaScript heap
@@ -1816,6 +1816,13 @@ class EXPORT Exception {
 
 typedef int* (*CounterLookupCallback)(const char* name);
 
+typedef void* (*CreateHistogramCallback)(const char* name,
+                                         int min,
+                                         int max,
+                                         size_t buckets);
+
+typedef void (*AddHistogramSampleCallback)(void* histogram, int sample);
+
 // --- F a i l e d A c c e s s C h e c k C a l l b a c k ---
 typedef void (*FailedAccessCheckCallback)(Local<Object> target,
                                           AccessType type,
@@ -1905,6 +1912,15 @@ class EXPORT V8 {
    */
   static void SetCounterFunction(CounterLookupCallback);
 
+  /**
+   * Enables the host application to provide a mechanism for recording
+   * histograms. The CreateHistogram function returns a
+   * histogram which will later be passed to the AddHistogramSample
+   * function.
+   */
+  static void SetCreateHistogramFunction(CreateHistogramCallback);
+  static void SetAddHistogramSampleFunction(AddHistogramSampleCallback);
+
   /**
    * Enables the computation of a sliding window of states. The sliding
    * window information is recorded in statistics counters.
index 54239cfb56811c75ade7eddd7751551d464b22be..bb0747a14187061696314f3f09055fe32b2b82d5 100644 (file)
@@ -2700,6 +2700,15 @@ void V8::SetCounterFunction(CounterLookupCallback callback) {
   i::StatsTable::SetCounterFunction(callback);
 }
 
+void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
+  if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
+  i::StatsTable::SetCreateHistogramFunction(callback);
+}
+
+void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
+  if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
+  i::StatsTable::SetAddHistogramSampleFunction(callback);
+}
 
 void V8::EnableSlidingStateWindow() {
   if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
index 645088515f3ae3536028ba503f8d0b364b5c4642..3fd74acf67170646a9182a70ec710aa9b008a545 100644 (file)
@@ -110,10 +110,10 @@ static Handle<JSFunction> MakeFunction(bool is_global,
   // Measure how long it takes to do the compilation; only take the
   // rest of the function into account to avoid overlap with the
   // parsing statistics.
-  StatsRate* rate = is_eval
+  HistogramTimer* rate = is_eval
       ? &Counters::compile_eval
       : &Counters::compile;
-  StatsRateScope timer(rate);
+  HistogramTimerScope timer(rate);
 
   // Compile the code.
   Handle<Code> code = MakeCode(lit, script, context, is_eval);
@@ -300,7 +300,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
   // Measure how long it takes to do the lazy compilation; only take
   // the rest of the function into account to avoid overlap with the
   // lazy parsing statistics.
-  StatsRateScope timer(&Counters::compile_lazy);
+  HistogramTimerScope timer(&Counters::compile_lazy);
 
   // Compile the code.
   Handle<Code> code = MakeCode(lit, script, Handle<Context>::null(), false);
index 8878ec560a5f62cd12db231edfe1b1428220e11f..bf9b8d8b06a8db10f7e360da4012dbcd3961fe0d 100644 (file)
@@ -33,6 +33,8 @@
 namespace v8 { namespace internal {
 
 CounterLookupCallback StatsTable::lookup_function_ = NULL;
+CreateHistogramCallback StatsTable::create_histogram_function_ = NULL;
+AddHistogramSampleCallback StatsTable::add_histogram_sample_function_ = NULL;
 
 // Start the timer.
 void StatsCounterTimer::Start() {
@@ -53,4 +55,23 @@ void StatsCounterTimer::Stop() {
   counter_.Increment(milliseconds);
 }
 
+// Start the timer.
+void HistogramTimer::Start() {
+  if (GetHistogram() != NULL) {
+    stop_time_ = 0;
+    start_time_ = OS::Ticks();
+  }
+}
+
+// Stop the timer and record the results.
+void HistogramTimer::Stop() {
+  if (histogram_ != NULL) {
+    stop_time_ = OS::Ticks();
+
+    // Compute the delta between start and stop, in milliseconds.
+    int milliseconds = static_cast<int>(stop_time_ - start_time_) / 1000;
+    StatsTable::AddHistogramSample(histogram_, milliseconds);
+  }
+}
+
 } }  // namespace v8::internal
index 0e239c8062d13646e4bca451b3bae7957326e188..df1c70a91bfcad22cb2782a51152e5a57a20d84d 100644 (file)
@@ -42,6 +42,18 @@ class StatsTable : public AllStatic {
     lookup_function_ = f;
   }
 
+  // Register an application-defined function to create
+  // a histogram for passing to the AddHistogramSample function
+  static void SetCreateHistogramFunction(CreateHistogramCallback f) {
+    create_histogram_function_ = f;
+  }
+
+  // Register an application-defined function to add a sample
+  // to a histogram created with CreateHistogram function
+  static void SetAddHistogramSampleFunction(AddHistogramSampleCallback f) {
+    add_histogram_sample_function_ = f;
+  }
+
   static bool HasCounterFunction() {
     return lookup_function_ != NULL;
   }
@@ -57,8 +69,30 @@ class StatsTable : public AllStatic {
     return lookup_function_(name);
   }
 
+  // Create a histogram by name. If the create is successful,
+  // returns a non-NULL pointer for use with AddHistogramSample
+  // function. min and max define the expected minimum and maximum
+  // sample values. buckets is the maximum number of buckets
+  // that the samples will be grouped into.
+  static void *CreateHistogram(const char* name,
+                               int min,
+                               int max,
+                               size_t buckets) {
+    if (!create_histogram_function_) return NULL;
+    return create_histogram_function_(name, min, max, buckets);
+  }
+
+  // Add a sample to a histogram created with the CreateHistogram
+  // function.
+  static void AddHistogramSample(void* histogram, int sample) {
+    if (!add_histogram_sample_function_) return;
+    return add_histogram_sample_function_(histogram, sample);
+  }
+
  private:
   static CounterLookupCallback lookup_function_;
+  static CreateHistogramCallback create_histogram_function_;
+  static AddHistogramSampleCallback add_histogram_sample_function_;
 };
 
 // StatsCounters are dynamically created values which can be tracked in
@@ -152,44 +186,50 @@ struct StatsCounterTimer {
   }
 };
 
-// A StatsRate is a combination of both a timer and a counter so that
-// several statistics can be produced:
-//    min, max, avg, count, total
-//
-// For example:
-//   StatsCounter c = { { { L"t:myrate", NULL, false }, 0, 0 },
-//                      { L"c:myrate", NULL, false } };
-struct StatsRate {
-  StatsCounterTimer timer_;
-  StatsCounter counter_;
+// A HistogramTimer allows distributions of results to be created
+// HistogramTimer t = { L"foo", NULL, false, 0, 0 };
+struct HistogramTimer {
+  const char* name_;
+  void* histogram_;
+  bool lookup_done_;
 
-  // Starts the rate timer.
-  void Start() {
-    timer_.Start();
+  int64_t start_time_;
+  int64_t stop_time_;
+
+  // Start the timer.
+  void Start();
+
+  // Stop the timer and record the results.
+  void Stop();
+
+  // Returns true if the timer is running.
+  bool Running() {
+    return (histogram_ != NULL) && (start_time_ != 0) && (stop_time_ == 0);
   }
 
-  // Stops the rate and records the time.
-  void Stop() {
-    if (timer_.Running()) {
-      timer_.Stop();
-      counter_.Increment();
+ protected:
+  // Returns the handle to the histogram.
+  void* GetHistogram() {
+    if (!lookup_done_) {
+      lookup_done_ = true;
+      histogram_ = StatsTable::CreateHistogram(name_, 0, 10000, 50);
     }
+    return histogram_;
   }
 };
 
-
-// Helper class for scoping a rate.
-class StatsRateScope BASE_EMBEDDED {
+// Helper class for scoping a HistogramTimer.
+class HistogramTimerScope BASE_EMBEDDED {
  public:
-  explicit StatsRateScope(StatsRate* rate) :
-      rate_(rate) {
-    rate_->Start();
+  explicit HistogramTimerScope(HistogramTimer* timer) :
+  timer_(timer) {
+    timer_->Start();
   }
-  ~StatsRateScope() {
-    rate_->Stop();
+  ~HistogramTimerScope() {
+    timer_->Stop();
   }
  private:
-  StatsRate* rate_;
+  HistogramTimer* timer_;
 };
 
 
index 481895ba2d7ebe128b1b60da77ce46cc690ccd89..eade646b82bd0fcc4dbfca356465b9848aa8a2a8 100644 (file)
@@ -310,7 +310,7 @@ void Heap::CollectAllGarbageIfContextDisposed() {
   // contexts are disposed and leave it to the embedder to make
   // informed decisions about when to force a collection.
   if (!FLAG_expose_gc && context_disposed_pending_) {
-    StatsRateScope scope(&Counters::gc_context);
+    HistogramTimerScope scope(&Counters::gc_context);
     CollectAllGarbage();
   }
   context_disposed_pending_ = false;
@@ -345,7 +345,7 @@ bool Heap::CollectGarbage(int requested_size, AllocationSpace space) {
     // Tell the tracer which collector we've selected.
     tracer.set_collector(collector);
 
-    StatsRate* rate = (collector == SCAVENGER)
+    HistogramTimer* rate = (collector == SCAVENGER)
         ? &Counters::gc_scavenger
         : &Counters::gc_compactor;
     rate->Start();
index 5487bf369050ab0d9303130fbf72c60ac5853564..c4bd9b3e055894a9da2d24d6ec0786037213c2ba 100644 (file)
@@ -1075,7 +1075,7 @@ Parser::Parser(Handle<Script> script,
 
 
 bool Parser::PreParseProgram(unibrow::CharacterStream* stream) {
-  StatsRateScope timer(&Counters::pre_parse);
+  HistogramTimerScope timer(&Counters::pre_parse);
   StackGuard guard;
   AssertNoZoneAllocation assert_no_zone_allocation;
   AssertNoAllocation assert_no_allocation;
@@ -1098,7 +1098,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
                                       bool in_global_context) {
   ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
 
-  StatsRateScope timer(&Counters::parse);
+  HistogramTimerScope timer(&Counters::parse);
   StringShape shape(*source);
   Counters::total_parse_size.Increment(source->length(shape));
 
@@ -1151,7 +1151,7 @@ FunctionLiteral* Parser::ParseLazy(Handle<String> source,
                                    int start_position,
                                    bool is_expression) {
   ZoneScope zone_scope(DONT_DELETE_ON_EXIT);
-  StatsRateScope timer(&Counters::parse_lazy);
+  HistogramTimerScope timer(&Counters::parse_lazy);
   source->TryFlattenIfNotFlat(StringShape(*source));
   StringShape shape(*source);
   Counters::total_parse_size.Increment(source->length(shape));
index 473dbd359be4d8a405da93f1980d2c286ba834bf..3a8286a64967b69487dd667f39fe3a0c882d4b38 100644 (file)
 
 namespace v8 { namespace internal {
 
-#define SR(name, caption) \
-  StatsRate Counters::name = { \
-  { { "t:" #caption, NULL, false }, 0, 0 }, \
-  { "c:" #caption, NULL, false } };
+#define HT(name, caption) \
+  HistogramTimer Counters::name = { #caption, NULL, false, 0, 0 }; \
 
-  STATS_RATE_LIST(SR)
+  HISTOGRAM_TIMER_LIST(HT)
 #undef SR
 
 #define SC(name, caption) \
index 69de3594e318dfc5ae2aef8988d88449de7b09a8..20e4c163da1418dd5f312eb8c87c6722c1dc7b1e 100644 (file)
 
 namespace v8 { namespace internal {
 
-#define STATS_RATE_LIST(SR)                                             \
-  SR(gc_compactor, V8.GCCompactor) /* GC Compactor time */              \
-  SR(gc_scavenger, V8.GCScavenger) /* GC Scavenger time */              \
-  SR(gc_context, V8.GCContext)     /* GC context cleanup time */        \
-  SR(compile, V8.Compile)          /* Compile time*/                    \
-  SR(compile_eval, V8.CompileEval) /* Eval compile time */              \
-  SR(compile_lazy, V8.CompileLazy) /* Lazy compile time */              \
-  SR(parse, V8.Parse)              /* Parse time */                     \
-  SR(parse_lazy, V8.ParseLazy)     /* Lazy parse time */                \
-  SR(pre_parse, V8.PreParse)       /* Pre-parse time */
+#define HISTOGRAM_TIMER_LIST(HT)                                 \
+  HT(gc_compactor, V8.GCCompactor) /* GC Compactor time */       \
+  HT(gc_scavenger, V8.GCScavenger) /* GC Scavenger time */       \
+  HT(gc_context, V8.GCContext)     /* GC context cleanup time */ \
+  HT(compile, V8.Compile)          /* Compile time*/             \
+  HT(compile_eval, V8.CompileEval) /* Eval compile time */       \
+  HT(compile_lazy, V8.CompileLazy) /* Lazy compile time */       \
+  HT(parse, V8.Parse)              /* Parse time */              \
+  HT(parse_lazy, V8.ParseLazy)     /* Lazy parse time */         \
+  HT(pre_parse, V8.PreParse)       /* Pre-parse time */
 
 // WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC
 // Intellisense to crash.  It was broken into two macros (each of length 40
@@ -129,10 +129,10 @@ namespace v8 { namespace internal {
 // This file contains all the v8 counters that are in use.
 class Counters : AllStatic {
  public:
-#define SR(name, caption) \
-  static StatsRate name;
-  STATS_RATE_LIST(SR)
-#undef SR
+#define HT(name, caption) \
+  static HistogramTimer name;
+  HISTOGRAM_TIMER_LIST(HT)
+#undef HT
 
 #define SC(name, caption) \
   static StatsCounter name;
@@ -142,7 +142,7 @@ class Counters : AllStatic {
 
   enum Id {
 #define RATE_ID(name, caption) k_##name,
-    STATS_RATE_LIST(RATE_ID)
+    HISTOGRAM_TIMER_LIST(RATE_ID)
 #undef RATE_ID
 #define COUNTER_ID(name, caption) k_##name,
   STATS_COUNTER_LIST_1(COUNTER_ID)