Profiler improvements
authorjkummerow <jkummerow@chromium.org>
Tue, 20 Jan 2015 16:06:03 +0000 (08:06 -0800)
committerCommit bot <commit-bot@chromium.org>
Tue, 20 Jan 2015 16:06:09 +0000 (16:06 +0000)
(1) --prof-cpp: Collects ticks like --prof, but ignores code creation events to reduce distortion (so all JS ticks will be "unaccounted"). Useful for profiling C++ code.
(2) --timed-range flag for tick processor: Ignores ticks before the first and after the last call to Date.now(). Useful for focusing on the timed section of a test.

Review URL: https://codereview.chromium.org/802333002

Cr-Commit-Position: refs/heads/master@{#26168}

13 files changed:
src/flag-definitions.h
src/isolate.cc
src/log-utils.h
src/log.cc
src/runtime/runtime-date.cc
test/mjsunit/tools/tickprocessor-test.default
test/mjsunit/tools/tickprocessor-test.ignore-unknown
test/mjsunit/tools/tickprocessor-test.separate-ic
test/mjsunit/tools/tickprocessor.js
tools/logreader.js
tools/profile.js
tools/tickprocessor-driver.js
tools/tickprocessor.js

index 03e22df4ae32a63f10167d00bf8b31d30b56a8f2..2cf77a3a4141ef6ede46e387b9450c480c21c2ee 100644 (file)
@@ -860,6 +860,8 @@ DEFINE_BOOL(log_snapshot_positions, false,
 DEFINE_BOOL(log_suspect, false, "Log suspect operations.")
 DEFINE_BOOL(prof, false,
             "Log statistical profiling information (implies --log-code).")
+DEFINE_BOOL(prof_cpp, false, "Like --prof, but ignore generated code.")
+DEFINE_IMPLICATION(prof, prof_cpp)
 DEFINE_BOOL(prof_browser_mode, true,
             "Used with --prof, turns on browser-compatible mode for profiling.")
 DEFINE_BOOL(log_regexp, false, "Log regular expression execution.")
index 9cad13f77938caff3988708de00d4ed6d084bef8..3a87d746a3d6423ed658af8a6a0e62f1e989eb9d 100644 (file)
@@ -2115,19 +2115,6 @@ bool Isolate::Init(Deserializer* des) {
     std::ofstream(GetTurboCfgFileName().c_str(), std::ios_base::trunc);
   }
 
-  // If we are deserializing, log non-function code objects and compiled
-  // functions found in the snapshot.
-  if (!create_heap_objects &&
-      (FLAG_log_code ||
-       FLAG_ll_prof ||
-       FLAG_perf_jit_prof ||
-       FLAG_perf_basic_prof ||
-       logger_->is_logging_code_events())) {
-    HandleScope scope(this);
-    LOG(this, LogCodeObjects());
-    LOG(this, LogCompiledFunctions());
-  }
-
   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)),
            Internals::kIsolateEmbedderDataOffset);
   CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)),
index ef285e6d68c6dc8e4addd893f5af0220e40b279c..3856f6062f6f755f5b826850bcdc6771d05f5fc2 100644 (file)
@@ -22,10 +22,10 @@ class Log {
   void stop() { is_stopped_ = true; }
 
   static bool InitLogAtStart() {
-    return FLAG_log || FLAG_log_api || FLAG_log_code || FLAG_log_gc
-        || FLAG_log_handles || FLAG_log_suspect || FLAG_log_regexp
-        || FLAG_ll_prof || FLAG_perf_basic_prof || FLAG_perf_jit_prof
-        || FLAG_log_internal_timer_events;
+    return FLAG_log || FLAG_log_api || FLAG_log_code || FLAG_log_gc ||
+           FLAG_log_handles || FLAG_log_suspect || FLAG_log_regexp ||
+           FLAG_ll_prof || FLAG_perf_basic_prof || FLAG_perf_jit_prof ||
+           FLAG_log_internal_timer_events || FLAG_prof_cpp;
   }
 
   // Frees all resources acquired in Initialize and Open... functions.
index f0ca8de755fb42cec4703d836685013b92784437..31460b6ce54457250728859a15d64fd267cbb314 100644 (file)
@@ -903,7 +903,7 @@ void Logger::ApiNamedSecurityCheck(Object* key) {
 void Logger::SharedLibraryEvent(const std::string& library_path,
                                 uintptr_t start,
                                 uintptr_t end) {
-  if (!log_->IsEnabled() || !FLAG_prof) return;
+  if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
   Log::MessageBuilder msg(log_);
   msg.Append("shared-library,\"%s\",0x%08" V8PRIxPTR ",0x%08" V8PRIxPTR,
              library_path.c_str(), start, end);
@@ -1516,7 +1516,7 @@ void Logger::DebugEvent(const char* event_type, Vector<uint16_t> parameter) {
 
 
 void Logger::TickEvent(TickSample* sample, bool overflow) {
-  if (!log_->IsEnabled() || !FLAG_prof) return;
+  if (!log_->IsEnabled() || !FLAG_prof_cpp) return;
   Log::MessageBuilder msg(log_);
   msg.Append("%s,", kLogEventsNames[TICK_EVENT]);
   msg.AppendAddress(sample->pc);
@@ -1861,9 +1861,9 @@ bool Logger::SetUp(Isolate* isolate) {
     is_logging_ = true;
   }
 
-  if (FLAG_log_internal_timer_events || FLAG_prof) timer_.Start();
+  if (FLAG_log_internal_timer_events || FLAG_prof_cpp) timer_.Start();
 
-  if (FLAG_prof) {
+  if (FLAG_prof_cpp) {
     profiler_ = new Profiler(isolate);
     is_logging_ = true;
     profiler_->Engage();
index 65d8fc63ac76000c6661ade6e74967bde757fda4..4caf27de0f403c0fc8cd5471e4b340f886a881b9 100644 (file)
@@ -70,7 +70,7 @@ RUNTIME_FUNCTION(Runtime_ThrowNotDateError) {
 RUNTIME_FUNCTION(Runtime_DateCurrentTime) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 0);
-  if (FLAG_log_timer_events) LOG(isolate, CurrentTimeEvent());
+  if (FLAG_log_timer_events || FLAG_prof_cpp) LOG(isolate, CurrentTimeEvent());
 
   // According to ECMA-262, section 15.9.1, page 117, the precision of
   // the number in a Date object representing a particular instant in
index c2fe441e19882fb164667921e1628c967495d8a7..943ec33553be01c7826647f9c162a44cd5401654 100644 (file)
@@ -7,7 +7,6 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
  [JavaScript]:
    ticks  total  nonlib   name
-      1    7.7%   11.1%  LazyCompile: exp native math.js:41
 
  [C++]:
    ticks  total  nonlib   name
@@ -18,7 +17,7 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
  [Summary]:
    ticks  total  nonlib   name
-      1    7.7%   11.1%  JavaScript
+      0    0.0%    0.0%  JavaScript
       5   38.5%   55.6%  C++
       0    0.0%    0.0%  GC
       4   30.8%          Shared libraries
@@ -45,6 +44,10 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
       2  100.0%    LazyCompile: exp native math.js:41
       2  100.0%      Script: exp.js
 
+      2   15.4%  UNKNOWN
+      1   50.0%    LazyCompile: exp native math.js:41
+      1  100.0%      Script: exp.js
+
       1    7.7%  v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
       1  100.0%    Script: exp.js
 
@@ -57,6 +60,3 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
       1  100.0%    LazyCompile: exp native math.js:41
       1  100.0%      Script: exp.js
 
-      1    7.7%  LazyCompile: exp native math.js:41
-      1  100.0%    Script: exp.js
-
index 263cec551e87f4f8f1622401faeb4c2c14e5cc2c..1dbf71baa910064f6f3daca0f80ab0b930ba3a62 100644 (file)
@@ -7,7 +7,6 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
  [JavaScript]:
    ticks  total  nonlib   name
-      1    9.1%   14.3%  LazyCompile: exp native math.js:41
 
  [C++]:
    ticks  total  nonlib   name
@@ -18,7 +17,7 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
  [Summary]:
    ticks  total  nonlib   name
-      1    9.1%   14.3%  JavaScript
+      0    0.0%    0.0%  JavaScript
       5   45.5%   71.4%  C++
       0    0.0%    0.0%  GC
       4   36.4%          Shared libraries
@@ -44,6 +43,10 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
       2  100.0%    LazyCompile: exp native math.js:41
       2  100.0%      Script: exp.js
 
+      2   18.2%  UNKNOWN
+      1   50.0%    LazyCompile: exp native math.js:41
+      1  100.0%      Script: exp.js
+
       1    9.1%  v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
       1  100.0%    Script: exp.js
 
@@ -56,6 +59,3 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
       1  100.0%    LazyCompile: exp native math.js:41
       1  100.0%      Script: exp.js
 
-      1    9.1%  LazyCompile: exp native math.js:41
-      1  100.0%    Script: exp.js
-
index aee1d1f7924f8238eacd94d6a4ccfa0df988c154..52821e7b63f9fd37b777dedb0a0d2f2fe3b48731 100644 (file)
@@ -9,7 +9,6 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
    ticks  total  nonlib   name
       1    7.7%   11.1%  LoadIC: j
       1    7.7%   11.1%  LoadIC: i
-      1    7.7%   11.1%  LazyCompile: exp native math.js:41
 
  [C++]:
    ticks  total  nonlib   name
@@ -20,7 +19,7 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
  [Summary]:
    ticks  total  nonlib   name
-      3   23.1%   33.3%  JavaScript
+      2   15.4%   22.2%  JavaScript
       5   38.5%   55.6%  C++
       0    0.0%    0.0%  GC
       4   30.8%          Shared libraries
@@ -47,6 +46,10 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
       2  100.0%    LazyCompile: exp native math.js:41
       2  100.0%      Script: exp.js
 
+      2   15.4%  UNKNOWN
+      1   50.0%    LazyCompile: exp native math.js:41
+      1  100.0%      Script: exp.js
+
       1    7.7%  v8::internal::JSObject::LookupOwnRealNamedProperty(v8::internal::String*, v8::internal::LookupResult*)
       1  100.0%    Script: exp.js
 
@@ -63,6 +66,3 @@ Statistical profiling result from v8.log, (13 ticks, 2 unaccounted, 0 excluded).
 
       1    7.7%  LoadIC: i
 
-      1    7.7%  LazyCompile: exp native math.js:41
-      1  100.0%    Script: exp.js
-
index f460d349bb553a7d98b08aba3fff3d9cd40d6359..b04b9a1765b38fffa8572ee38510a9e18a56e661 100644 (file)
@@ -323,7 +323,7 @@ CppEntriesProviderMock.prototype.parseVmSymbols = function(
 
 
 function PrintMonitor(outputOrFileName) {
-  var expectedOut = typeof outputOrFileName == 'string' ?
+  var expectedOut = this.expectedOut = typeof outputOrFileName == 'string' ?
       this.loadExpectedOutput(outputOrFileName) : outputOrFileName;
   var outputPos = 0;
   var diffs = this.diffs = [];
@@ -359,7 +359,10 @@ PrintMonitor.prototype.loadExpectedOutput = function(fileName) {
 PrintMonitor.prototype.finish = function() {
   print = this.oldPrint;
   if (this.diffs.length > 0 || this.unexpectedOut != null) {
+    print("===== actual output: =====");
     print(this.realOut.join('\n'));
+    print("===== expected output: =====");
+    print(this.expectedOut.join('\n'));
     assertEquals([], this.diffs);
     assertNull(this.unexpectedOut);
   }
@@ -383,7 +386,8 @@ function driveTickProcessorTest(
                              stateFilter,
                              undefined,
                              "0",
-                             "auto,auto");
+                             "auto,auto",
+                             false);
   var pm = new PrintMonitor(testsPath + refOutput);
   tp.processLogFileInTest(testsPath + logInput);
   tp.printStatistics();
index 5f0ec7f6c7a687829aefd08649d043ea16c2d0a7..ceac2b826800e3375db94454fb3cf068af2107ff 100644 (file)
  *
  * @param {Array.<Object>} dispatchTable A table used for parsing and processing
  *     log records.
+ * @param {boolean} timedRange Ignore ticks outside timed range.
  * @constructor
  */
-function LogReader(dispatchTable) {
+function LogReader(dispatchTable, timedRange) {
   /**
    * @type {Array.<Object>}
    */
   this.dispatchTable_ = dispatchTable;
 
+  /**
+   * @type {boolean}
+   */
+  this.timedRange_ = timedRange;
+
   /**
    * Current line.
    * @type {number}
@@ -54,6 +60,18 @@ function LogReader(dispatchTable) {
    * @type {CsvParser}
    */
   this.csvParser_ = new CsvParser();
+
+  /**
+   * Keeps track of whether we've seen a "current-time" tick yet.
+   * @type {boolean}
+   */
+  this.hasSeenTimerMarker_ = false;
+
+  /**
+   * List of log lines seen since last "current-time" tick.
+   * @type {Array.<String>}
+   */
+  this.logLinesSinceLastTimerMarker_ = [];
 };
 
 
@@ -83,7 +101,24 @@ LogReader.prototype.processLogChunk = function(chunk) {
  * @param {string} line A line of log.
  */
 LogReader.prototype.processLogLine = function(line) {
-  this.processLog_([line]);
+  if (!this.timedRange_) {
+    this.processLog_([line]);
+    return;
+  }
+  if (line.startsWith("current-time")) {
+    if (this.hasSeenTimerMarker_) {
+      this.processLog_(this.logLinesSinceLastTimerMarker_);
+      this.logLinesSinceLastTimerMarker_ = [];
+    } else {
+      this.hasSeenTimerMarker_ = true;
+    }
+  } else {
+    if (this.hasSeenTimerMarker_) {
+      this.logLinesSinceLastTimerMarker_.push(line);
+    } else if (!line.startsWith("tick")) {
+      this.processLog_([line]);
+    }
+  }
 };
 
 
index a06cd3a5ff0fff19232fee60bf78e5ba2a7a1129..f0814a2f0d9cc3303cf5ae8f5633058a1e7243cd 100644 (file)
@@ -257,26 +257,28 @@ Profile.prototype.resolveAndFilterFuncs_ = function(stack) {
     var entry = this.codeMap_.findEntry(stack[i]);
     if (entry) {
       var name = entry.getName();
-      if (i == 0 && (entry.type == 'CPP' || entry.type == 'SHARED_LIB')) {
+      if (i === 0 && (entry.type === 'CPP' || entry.type === 'SHARED_LIB')) {
         look_for_first_c_function = true;
       }
-      if (look_for_first_c_function) {
-        if (entry.type == 'CPP') {
-          last_seen_c_function = name;
-        } else if (i > 0 && last_seen_c_function != '') {
-          if (this.c_entries_[last_seen_c_function] === undefined) {
-            this.c_entries_[last_seen_c_function] = 0;
-          }
-          this.c_entries_[last_seen_c_function]++;
-          look_for_first_c_function = false;  // Found it, we're done.
-        }
+      if (look_for_first_c_function && entry.type === 'CPP') {
+        last_seen_c_function = name;
       }
       if (!this.skipThisFunction(name)) {
         result.push(name);
       }
     } else {
-      this.handleUnknownCode(
-          Profile.Operation.TICK, stack[i], i);
+      this.handleUnknownCode(Profile.Operation.TICK, stack[i], i);
+      if (i === 0) result.push("UNKNOWN");
+    }
+    if (look_for_first_c_function &&
+        i > 0 &&
+        (!entry || entry.type !== 'CPP') &&
+        last_seen_c_function !== '') {
+      if (this.c_entries_[last_seen_c_function] === undefined) {
+        this.c_entries_[last_seen_c_function] = 0;
+      }
+      this.c_entries_[last_seen_c_function]++;
+      look_for_first_c_function = false;  // Found it, we're done.
     }
   }
   return result;
index 8ba3326f630d1d27821226845ccc0a8f690067e8..16054186afd74e92a79b1cb7951dbf075b2786eb 100644 (file)
@@ -75,6 +75,7 @@ var tickProcessor = new TickProcessor(
   snapshotLogProcessor,
   params.distortion,
   params.range,
-  sourceMap);
+  sourceMap,
+  params.timedRange);
 tickProcessor.processLogFile(params.logFileName);
 tickProcessor.printStatistics();
index d54471795f6c17912f798a5b20e0acb6c95a4f0e..05f42076bd97ffaf010f2251145bb6abb6973ad5 100644 (file)
@@ -154,7 +154,8 @@ function TickProcessor(
     snapshotLogProcessor,
     distortion,
     range,
-    sourceMap) {
+    sourceMap,
+    timedRange) {
   LogReader.call(this, {
       'shared-library': { parsers: [null, parseInt, parseInt],
           processor: this.processSharedLibrary },
@@ -187,10 +188,12 @@ function TickProcessor(
       'function-move': null,
       'function-delete': null,
       'heap-sample-item': null,
+      'current-time': null,  // Handled specially, not parsed.
       // Obsolete row types.
       'code-allocate': null,
       'begin-code-region': null,
-      'end-code-region': null });
+      'end-code-region': null },
+      timedRange);
 
   this.cppEntriesProvider_ = cppEntriesProvider;
   this.callGraphSize_ = callGraphSize;
@@ -292,7 +295,7 @@ TickProcessor.prototype.isCppCode = function(name) {
 
 
 TickProcessor.prototype.isJsCode = function(name) {
-  return !(name in this.codeTypes_);
+  return name !== "UNKNOWN" && !(name in this.codeTypes_);
 };
 
 
@@ -875,7 +878,9 @@ function ArgumentsProcessor(args) {
     '--distortion': ['distortion', 0,
         'Specify the logging overhead in picoseconds'],
     '--source-map': ['sourceMap', null,
-        'Specify the source map that should be used for output']
+        'Specify the source map that should be used for output'],
+    '--timed-range': ['timedRange', true,
+        'Ignore ticks before first and after last Date.now() call']
   };
   this.argsDispatch_['--js'] = this.argsDispatch_['-j'];
   this.argsDispatch_['--gc'] = this.argsDispatch_['-g'];
@@ -896,7 +901,8 @@ ArgumentsProcessor.DEFAULTS = {
   targetRootFS: '',
   nm: 'nm',
   range: 'auto,auto',
-  distortion: 0
+  distortion: 0,
+  timedRange: false
 };