Revision: 13074
Author: [email protected]
Date: Wed Nov 28 03:01:10 2012
Log: Include more information in --prof log.
Main changes:
- include timestamps in profile ticks
- include code kind in code create events
- time execution in external code
- changed plot-timer-events.js to show the code kind being executed
[email protected]
BUG=
Review URL: https://chromiumcodereview.appspot.com/11428025
http://code.google.com/p/v8/source/detail?r=13074
Modified:
/branches/bleeding_edge/src/log.cc
/branches/bleeding_edge/src/log.h
/branches/bleeding_edge/src/vm-state-inl.h
/branches/bleeding_edge/test/cctest/test-log.cc
/branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test-func-info.log
/branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test.log
/branches/bleeding_edge/tools/plot-timer-events
/branches/bleeding_edge/tools/plot-timer-events.js
/branches/bleeding_edge/tools/tickprocessor.js
=======================================
--- /branches/bleeding_edge/src/log.cc Mon Nov 26 00:56:59 2012
+++ /branches/bleeding_edge/src/log.cc Wed Nov 28 03:01:10 2012
@@ -716,6 +716,20 @@
}
+void Logger::ExternalSwitch(StateTag old_tag, StateTag new_tag) {
+ if (old_tag != EXTERNAL && new_tag == EXTERNAL) {
+ enter_external_ = OS::Ticks();
+ }
+ if (old_tag == EXTERNAL && new_tag != EXTERNAL && enter_external_ != 0) {
+ TimerEvent("V8.External", enter_external_, OS::Ticks());
+ enter_external_ = 0;
+ }
+}
+
+
+int64_t Logger::enter_external_ = 0;
+
+
void Logger::TimerEventScope::LogTimerEvent() {
LOG(isolate_, TimerEvent(name_, start_, OS::Ticks()));
}
@@ -900,7 +914,7 @@
Address entry_point) {
if (!log_->IsEnabled() || !FLAG_log_code) return;
LogMessageBuilder msg(this);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,-3,",
kLogEventsNames[CODE_CREATION_EVENT],
kLogEventsNames[CALLBACK_TAG]);
msg.AppendAddress(entry_point);
@@ -956,9 +970,10 @@
}
if (!FLAG_log_code) return;
LogMessageBuilder msg(this);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
- kLogEventsNames[tag]);
+ kLogEventsNames[tag],
+ code->kind());
msg.AppendAddress(code->address());
msg.Append(",%d,\"", code->ExecutableSize());
for (const char* p = comment; *p != '\0'; p++) {
@@ -995,9 +1010,10 @@
}
if (!FLAG_log_code) return;
LogMessageBuilder msg(this);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
- kLogEventsNames[tag]);
+ kLogEventsNames[tag],
+ code->kind());
msg.AppendAddress(code->address());
msg.Append(",%d,\"", code->ExecutableSize());
msg.AppendDetailed(name, false);
@@ -1047,9 +1063,10 @@
LogMessageBuilder msg(this);
SmartArrayPointer<char> str =
name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
- kLogEventsNames[tag]);
+ kLogEventsNames[tag],
+ code->kind());
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s\",", code->ExecutableSize(), *str);
msg.AppendAddress(shared->address());
@@ -1094,9 +1111,10 @@
shared->DebugName()->ToCString(DISALLOW_NULLS,
ROBUST_STRING_TRAVERSAL);
SmartArrayPointer<char> sourcestr =
source->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
- kLogEventsNames[tag]);
+ kLogEventsNames[tag],
+ code->kind());
msg.AppendAddress(code->address());
msg.Append(",%d,\"%s %s:%d\",",
code->ExecutableSize(),
@@ -1130,9 +1148,10 @@
}
if (!FLAG_log_code) return;
LogMessageBuilder msg(this);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,%d,",
kLogEventsNames[CODE_CREATION_EVENT],
- kLogEventsNames[tag]);
+ kLogEventsNames[tag],
+ code->kind());
msg.AppendAddress(code->address());
msg.Append(",%d,\"args_count: %d\"", code->ExecutableSize(), args_count);
msg.Append('\n');
@@ -1167,7 +1186,7 @@
}
if (!FLAG_log_code) return;
LogMessageBuilder msg(this);
- msg.Append("%s,%s,",
+ msg.Append("%s,%s,-2,",
kLogEventsNames[CODE_CREATION_EVENT],
kLogEventsNames[REG_EXP_TAG]);
msg.AppendAddress(code->address());
@@ -1347,6 +1366,8 @@
msg.AppendAddress(sample->pc);
msg.Append(',');
msg.AppendAddress(sample->sp);
+ msg.Append(",%ld",
+ FLAG_log_timer_events ? static_cast<int>(OS::Ticks() - epoch_) : 0);
if (sample->has_external_callback) {
msg.Append(",1,");
msg.AppendAddress(sample->external_callback);
=======================================
--- /branches/bleeding_edge/src/log.h Mon Nov 26 00:56:59 2012
+++ /branches/bleeding_edge/src/log.h Wed Nov 28 03:01:10 2012
@@ -275,7 +275,10 @@
void SharedLibraryEvent(const wchar_t* library_path,
uintptr_t start,
uintptr_t end);
+
+ // ==== Events logged by --log-timer-events. ====
void TimerEvent(const char* name, int64_t start, int64_t end);
+ void ExternalSwitch(StateTag old_tag, StateTag new_tag);
class TimerEventScope {
public:
@@ -476,6 +479,7 @@
Address prev_code_;
int64_t epoch_;
+ static int64_t enter_external_;
friend class CpuProfiler;
};
=======================================
--- /branches/bleeding_edge/src/vm-state-inl.h Thu Nov 22 05:04:11 2012
+++ /branches/bleeding_edge/src/vm-state-inl.h Wed Nov 28 03:01:10 2012
@@ -66,6 +66,10 @@
LOG(isolate, UncheckedStringEvent("Entering", StateToString(tag)));
LOG(isolate, UncheckedStringEvent("From",
StateToString(previous_tag_)));
}
+
+ if (FLAG_log_timer_events) {
+ LOG(isolate, ExternalSwitch(previous_tag_, tag));
+ }
isolate_->SetCurrentVMState(tag);
}
@@ -79,6 +83,10 @@
LOG(isolate_,
UncheckedStringEvent("To", StateToString(previous_tag_)));
}
+
+ if (FLAG_log_timer_events) {
+ LOG(isolate_, ExternalSwitch(isolate_->current_vm_state(),
previous_tag_));
+ }
isolate_->SetCurrentVMState(previous_tag_);
}
=======================================
--- /branches/bleeding_edge/test/cctest/test-log.cc Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/test/cctest/test-log.cc Wed Nov 28 03:01:10 2012
@@ -392,7 +392,7 @@
i::EmbeddedVector<char, 100> ref_data;
i::OS::SNPrintF(ref_data,
- "code-creation,Callback,0x%"
V8PRIxPTR ",1,\"method1\"\0",
+ "code-creation,Callback,-3,0x%"
V8PRIxPTR ",1,\"method1\"\0",
ObjMethod1);
CHECK_NE(NULL, StrNStr(log.start(), ref_data.start(), log.length()));
@@ -435,21 +435,21 @@
EmbeddedVector<char, 100> prop1_getter_record;
i::OS::SNPrintF(prop1_getter_record,
- "code-creation,Callback,0x%" V8PRIxPTR ",1,\"get
prop1\"",
+ "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get
prop1\"",
Prop1Getter);
CHECK_NE(NULL,
StrNStr(log.start(), prop1_getter_record.start(),
log.length()));
EmbeddedVector<char, 100> prop1_setter_record;
i::OS::SNPrintF(prop1_setter_record,
- "code-creation,Callback,0x%" V8PRIxPTR ",1,\"set
prop1\"",
+ "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"set
prop1\"",
Prop1Setter);
CHECK_NE(NULL,
StrNStr(log.start(), prop1_setter_record.start(),
log.length()));
EmbeddedVector<char, 100> prop2_getter_record;
i::OS::SNPrintF(prop2_getter_record,
- "code-creation,Callback,0x%" V8PRIxPTR ",1,\"get
prop2\"",
+ "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get
prop2\"",
Prop2Getter);
CHECK_NE(NULL,
StrNStr(log.start(), prop2_getter_record.start(),
log.length()));
=======================================
---
/branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test-func-info.log
Mon Mar 21 11:13:27 2011
+++
/branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test-func-info.log
Wed Nov 28 03:01:10 2012
@@ -2,10 +2,10 @@
shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
profiler,"begin",1
-code-creation,Stub,0x424260,348,"CompareStub_GE"
-code-creation,LazyCompile,0x2a8100,18535,"DrawQube
3d-cube.js:188",0xf43abcac,
-code-creation,LazyCompile,0x480100,3908,"DrawLine
3d-cube.js:17",0xf43abc50,
-tick,0x424284,0xbfffeea0,0,0x480600,0,0x2aaaa5
-tick,0x42429f,0xbfffed88,0,0x480600,0,0x2aacb4
-tick,0x48063d,0xbfffec7c,0,0x2d0f7c,0,0x2aaec6
+code-creation,Stub,0,0x424260,348,"CompareStub_GE"
+code-creation,LazyCompile,0,0x2a8100,18535,"DrawQube
3d-cube.js:188",0xf43abcac,
+code-creation,LazyCompile,0,0x480100,3908,"DrawLine
3d-cube.js:17",0xf43abc50,
+tick,0x424284,0xbfffeea0,0,0,0x480600,0,0x2aaaa5
+tick,0x42429f,0xbfffed88,0,0,0x480600,0,0x2aacb4
+tick,0x48063d,0xbfffec7c,0,0,0x2d0f7c,0,0x2aaec6
profiler,"end"
=======================================
--- /branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test.log Mon
Mar 21 11:13:27 2011
+++ /branches/bleeding_edge/test/mjsunit/tools/tickprocessor-test.log Wed
Nov 28 03:01:10 2012
@@ -2,24 +2,24 @@
shared-library,"/lib32/libm-2.7.so",0xf7db6000,0xf7dd9000
shared-library,"ffffe000-fffff000",0xffffe000,0xfffff000
profiler,"begin",1
-code-creation,Stub,0xf540a100,474,"CEntryStub"
-code-creation,Script,0xf541cd80,736,"exp.js"
-code-creation,Stub,0xf541d0e0,47,"RuntimeStub_Math_exp"
-code-creation,LazyCompile,0xf541d120,145,"exp native math.js:41"
+code-creation,Stub,0,0xf540a100,474,"CEntryStub"
+code-creation,Script,0,0xf541cd80,736,"exp.js"
+code-creation,Stub,0,0xf541d0e0,47,"RuntimeStub_Math_exp"
+code-creation,LazyCompile,0,0xf541d120,145,"exp native math.js:41"
function-creation,0xf441d280,0xf541d120
-code-creation,LoadIC,0xf541d280,117,"j"
-code-creation,LoadIC,0xf541d360,63,"i"
-tick,0x80f82d1,0xffdfe880,0,0,0,0xf541ce5c
-tick,0x80f89a1,0xffdfecf0,0,0,0,0xf541ce5c
-tick,0x8123b5c,0xffdff1a0,0,0,0,0xf541d1a1,0xf541ceea
-tick,0x8123b65,0xffdff1a0,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf541d2be,0xffdff1e4,0,0,0
-tick,0xf541d320,0xffdff1dc,0,0,0
-tick,0xf541d384,0xffdff1d8,0,0,0
-tick,0xf7db94da,0xffdff0ec,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7db951c,0xffdff0f0,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7dbc508,0xffdff14c,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7dbff21,0xffdff198,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xf7edec90,0xffdff0ec,0,0,0,0xf541d1a1,0xf541ceea
-tick,0xffffe402,0xffdff488,0,0,0
+code-creation,LoadIC,0,0xf541d280,117,"j"
+code-creation,LoadIC,0,0xf541d360,63,"i"
+tick,0x80f82d1,0xffdfe880,0,0,0,0,0xf541ce5c
+tick,0x80f89a1,0xffdfecf0,0,0,0,0,0xf541ce5c
+tick,0x8123b5c,0xffdff1a0,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0x8123b65,0xffdff1a0,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf541d2be,0xffdff1e4,0,0,0,0
+tick,0xf541d320,0xffdff1dc,0,0,0,0
+tick,0xf541d384,0xffdff1d8,0,0,0,0
+tick,0xf7db94da,0xffdff0ec,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7db951c,0xffdff0f0,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7dbc508,0xffdff14c,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7dbff21,0xffdff198,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xf7edec90,0xffdff0ec,0,0,0,0,0xf541d1a1,0xf541ceea
+tick,0xffffe402,0xffdff488,0,0,0,0
profiler,"end"
=======================================
--- /branches/bleeding_edge/tools/plot-timer-events Thu Nov 22 05:04:11 2012
+++ /branches/bleeding_edge/tools/plot-timer-events Wed Nov 28 03:01:10 2012
@@ -34,6 +34,7 @@
# nm spits out 'no symbols found' messages to stderr.
cat $log_file | $d8_exec $tools_path/csvparser.js \
+ $tools_path/splaytree.js $tools_path/codemap.js \
$tools_path/logreader.js $tools_path/plot-timer-events.js \
2>/dev/null | gnuplot > timer-events.png
=======================================
--- /branches/bleeding_edge/tools/plot-timer-events.js Thu Nov 22 05:04:11
2012
+++ /branches/bleeding_edge/tools/plot-timer-events.js Wed Nov 28 03:01:10
2012
@@ -25,50 +25,83 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-var kExecutionName = 'V8.Execute';
+var kV8BinarySuffixes = ["/d8", "/libv8.so"];
+var kStackFrames = 8;
-var TimerEvents = {
- 'V8.Execute':
- { ranges: [], color: "#444444", pause: false, index: 1 },
- 'V8.CompileFullCode':
- { ranges: [], color: "#CC0000", pause: true, index: 2 },
- 'V8.RecompileSynchronous':
- { ranges: [], color: "#CC0044", pause: true, index: 3 },
- 'V8.RecompileParallel':
- { ranges: [], color: "#CC4499", pause: false, index: 4 },
- 'V8.CompileEval':
- { ranges: [], color: "#CC4400", pause: true, index: 5 },
- 'V8.Parse':
- { ranges: [], color: "#00CC00", pause: true, index: 6 },
- 'V8.PreParse':
- { ranges: [], color: "#44CC00", pause: true, index: 7 },
- 'V8.ParseLazy':
- { ranges: [], color: "#00CC44", pause: true, index: 8 },
- 'V8.GCScavenger':
- { ranges: [], color: "#0044CC", pause: true, index: 9 },
- 'V8.GCCompactor':
- { ranges: [], color: "#4444CC", pause: true, index: 10 },
- 'V8.GCContext':
- { ranges: [], color: "#4400CC", pause: true, index: 11 },
-}
+var kTimerEventWidth = 0.33;
+var kExecutionFrameWidth = 0.2;
+var kStackFrameWidth = 0.1;
+var kGapWidth = 0.05;
-var kNumRows = 11;
-var kBarWidth = 0.33;
-var kPauseTolerance = 0.05; // Milliseconds.
-var kY1Offset = 3;
-var kY2Factor = 5;
+var kPauseTolerance = 0.1; // Milliseconds.
+var kY1Offset = 10;
+
var kResX = 1600;
-var kResY = 400;
-var kLabelPadding = 5;
+var kResY = 600;
+var kPauseLabelPadding = 5;
var kNumPauseLabels = 7;
+var kTickHalfDuration = 0.5; // Milliseconds
+var kCodeKindLabelPadding = 100;
var kOverrideRangeStart = undefined;
var kOverrideRangeEnd = undefined;
+var num_timer_event = kY1Offset + 0.5;
+
+
+function TimerEvent(color, pause, no_execution) {
+ this.color = color;
+ this.pause = pause;
+ this.ranges = [];
+ this.no_execution = no_execution;
+ this.index = ++num_timer_event;
+}
+
+
+var TimerEvents = {
+ 'V8.Execute': new TimerEvent("#000000", false, false),
+ 'V8.External': new TimerEvent("#3399FF", false, true),
+ 'V8.CompileFullCode': new TimerEvent("#CC0000", true, true),
+ 'V8.RecompileSynchronous': new TimerEvent("#CC0044", true, true),
+ 'V8.RecompileParallel': new TimerEvent("#CC4499", false, false),
+ 'V8.CompileEval': new TimerEvent("#CC4400", true, true),
+ 'V8.Parse': new TimerEvent("#00CC00", true, true),
+ 'V8.PreParse': new TimerEvent("#44CC00", true, true),
+ 'V8.ParseLazy': new TimerEvent("#00CC44", true, true),
+ 'V8.GCScavenger': new TimerEvent("#0044CC", true, true),
+ 'V8.GCCompactor': new TimerEvent("#4444CC", true, true),
+ 'V8.GCContext': new TimerEvent("#4400CC", true, true),
+}
+
+var kExecutionEvent = TimerEvents['V8.Execute'];
+
+
+function CodeKind(color, kinds) {
+ this.color = color;
+ this.in_execution = [];
+ this.stack_frames = [];
+ for (var i = 0; i < kStackFrames; i++) this.stack_frames.push([]);
+ this.kinds = kinds;
+}
+
+
+var CodeKinds = {
+ 'external ': new CodeKind("#3399FF", [-3]),
+ 'reg.exp. ': new CodeKind("#0000FF", [-2]),
+ 'runtime ': new CodeKind("#000000", [-1]),
+ 'full code': new CodeKind("#DD0000", [0]),
+ 'opt code ': new CodeKind("#00EE00", [1]),
+ 'code stub': new CodeKind("#FF00FF", [2]),
+ 'built-in ': new CodeKind("#AA00AA", [3]),
+ 'inl.cache': new CodeKind("#4444AA", [4, 5, 6, 7, 8, 9, 10, 11, 12, 13]),
+}
+
+
var xrange_start = Infinity;
var xrange_end = 0;
var obj_index = 0;
var execution_pauses = [];
+var code_map = new CodeMap();
function Range(start, end) {
@@ -88,19 +121,89 @@
length /= 1000;
var end = start + length;
event.ranges.push(new Range(start, end));
- if (name == kExecutionName) {
+ if (event == kExecutionEvent) {
if (start < xrange_start) xrange_start = start;
if (end > xrange_end) xrange_end = end;
}
}
+
+
+function ProcessCodeCreateEvent(type, kind, address, size, name) {
+ var code_entry = new CodeMap.CodeEntry(size, name);
+ code_entry.kind = kind;
+ code_map.addCode(address, code_entry);
+}
+
+
+function ProcessCodeMoveEvent(from, to) {
+ code_map.moveCode(from, to);
+}
+
+
+function ProcessCodeDeleteEvent(address) {
+ code_map.deleteCode(address);
+}
+
+
+function ProcessSharedLibrary(name, start, end) {
+ var code_entry = new CodeMap.CodeEntry(end - start, name);
+ code_entry.kind = -3; // External code kind.
+ for (var i = 0; i < kV8BinarySuffixes.length; i++) {
+ var suffix = kV8BinarySuffixes[i];
+ if (name.indexOf(suffix, name.length - suffix.length) >= 0) {
+ code_entry.kind = -1; // V8 runtime code kind.
+ break;
+ }
+ }
+ code_map.addLibrary(start, code_entry);
+}
+
+
+function FindCodeKind(kind) {
+ for (name in CodeKinds) {
+ if (CodeKinds[name].kinds.indexOf(kind) >= 0) {
+ return CodeKinds[name];
+ }
+ }
+}
+
+
+function ProcessTickEvent(pc, sp, timer, unused_x, unused_y, vmstate,
stack) {
+ timer /= 1000;
+ var tick = new Range(timer - kTickHalfDuration, timer +
kTickHalfDuration);
+
+ var entry = code_map.findEntry(pc);
+ if (entry) {
+ FindCodeKind(entry.kind).in_execution.push(tick);
+ }
+
+ for (var i = 0; i < kStackFrames; i++) {
+ if (!stack[i]) break;
+ var entry = code_map.findEntry(stack[i]);
+ if (entry) {
+ FindCodeKind(entry.kind).stack_frames[i].push(tick);
+ }
+ }
+}
function CollectData() {
// Collect data from log.
var logreader = new LogReader(
- { 'timer-event' : { parsers: [null, parseInt, parseInt],
- processor: ProcessTimerEvent
- } });
+ { 'timer-event' : { parsers: [null, parseInt, parseInt],
+ processor: ProcessTimerEvent },
+ 'shared-library': { parsers: [null, parseInt, parseInt],
+ processor: ProcessSharedLibrary },
+ 'code-creation': { parsers: [null, parseInt, parseInt, parseInt,
null],
+ processor: ProcessCodeCreateEvent },
+ 'code-move': { parsers: [parseInt, parseInt],
+ processor: ProcessCodeMoveEvent },
+ 'code-delete': { parsers: [parseInt],
+ processor: ProcessCodeDeleteEvent },
+ 'tick': { parsers: [parseInt, parseInt, parseInt,
+ null, null, parseInt, 'var-args'],
+ processor: ProcessTickEvent },
+ });
var line;
while (line = readline()) {
@@ -112,25 +215,42 @@
var event = TimerEvents[name];
if (!event.pause) continue;
var ranges = event.ranges;
+ for (var j = 0; j < ranges.length; j++)
execution_pauses.push(ranges[j]);
+ }
+ execution_pauses = MergeRanges(execution_pauses);
+
+ // Knock out time not spent in javascript execution. Note that this also
+ // includes time spent external code, which do not contribute to
execution
+ // pauses.
+ var exclude_ranges = [];
+ for (name in TimerEvents) {
+ var event = TimerEvents[name];
+ if (!event.no_execution) continue;
+ var ranges = event.ranges;
// Add ranges of this event to the pause list.
for (var j = 0; j < ranges.length; j++) {
- execution_pauses.push(ranges[j]);
+ exclude_ranges.push(ranges[j]);
}
}
+
+ kExecutionEvent.ranges = MergeRanges(kExecutionEvent.ranges);
+ exclude_ranges = MergeRanges(exclude_ranges);
+ kExecutionEvent.ranges = ExcludeRanges(kExecutionEvent.ranges,
+ exclude_ranges);
}
-function drawBar(row, color, start, end) {
+function DrawBar(row, color, start, end, width) {
obj_index++;
command = "set object " + obj_index + " rect";
- command += " from " + start + ", " + (row - kBarWidth + kY1Offset);
- command += " to " + end + ", " + (row + kBarWidth + kY1Offset);
+ command += " from " + start + ", " + (row - width);
+ command += " to " + end + ", " + (row + width);
command += " fc rgb \"" + color + "\"";
print(command);
}
-function MergeRanges(ranges, merge_tolerance) {
+function MergeRanges(ranges) {
ranges.sort(function(a, b) { return a.start - b.start; });
var result = [];
var j = 0;
@@ -141,7 +261,7 @@
for (j = i + 1; j < ranges.length; j++) {
var next_range = ranges[j];
// Don't merge ranges if there is no overlap (including merge
tolerance).
- if (next_range.start >= merge_end + kPauseTolerance) break;
+ if (next_range.start > merge_end + kPauseTolerance) break;
// Merge ranges.
if (next_range.end > merge_end) { // Extend range end.
merge_end = next_range.end;
@@ -239,10 +359,9 @@
function GnuplotOutput() {
xrange_start = kOverrideRangeStart ? kOverrideRangeStart : xrange_start;
xrange_end = kOverrideRangeEnd ? kOverrideRangeEnd : xrange_end;
-
print("set terminal pngcairo size " + kResX + "," + kResY +
" enhanced font 'Helvetica,10'");
- print("set yrange [0:" + (kNumRows + kY1Offset + 1) + "]");
+ print("set yrange [0:" + (num_timer_event + 1) + "]");
print("set xlabel \"execution time in ms\"");
print("set xrange [" + xrange_start + ":" + xrange_end + "]");
print("set style fill pattern 2 bo 1");
@@ -255,57 +374,71 @@
var ytics = [];
for (name in TimerEvents) {
var index = TimerEvents[name].index;
- ytics.push('"' + name + '"' + ' ' + (index + kY1Offset));
+ ytics.push('"' + name + '"' + ' ' + index);
}
+ ytics.push('"code kind being executed"' + ' ' + (kY1Offset - 1));
+ ytics.push('"top ' + kStackFrames + ' js stack frames"' + ' ' +
+ (kY1Offset - 2));
+ ytics.push('"pause times" 0');
print("set ytics out nomirror (" + ytics.join(', ') + ")");
- // Smallest visible gap given our resolution.
- // We remove superfluous objects to go easy on Gnuplot.
- var tolerance = (xrange_end - xrange_start) / kResX / 2;
-
- // Sort, merge and remove invisible gaps for each time row.
- for (var name in TimerEvents) {
- var event = TimerEvents[name];
- event.ranges = MergeRanges(event.ranges, tolerance);
- }
-
- // Knock out execution pauses.
- var execution_event = TimerEvents[kExecutionName];
- var exclude_ranges = MergeRanges(execution_pauses, tolerance);
- execution_event.ranges = ExcludeRanges(execution_event.ranges,
- exclude_ranges);
- execution_event.ranges = MergeRanges(execution_event.ranges, tolerance);
-
// Plot timeline.
for (var name in TimerEvents) {
var event = TimerEvents[name];
- var ranges = event.ranges;
+ var ranges = MergeRanges(event.ranges);
for (var i = 0; i < ranges.length; i++) {
- drawBar(event.index, event.color, ranges[i].start, ranges[i].end);
+ DrawBar(event.index, event.color,
+ ranges[i].start, ranges[i].end,
+ kTimerEventWidth);
+ }
+ }
+
+ // Plot code kind gathered from ticks.
+ for (var name in CodeKinds) {
+ var code_kind = CodeKinds[name];
+ var offset = kY1Offset - 1;
+ // Top most frame.
+ var row = MergeRanges(code_kind.in_execution);
+ for (var j = 0; j < row.length; j++) {
+ DrawBar(offset, code_kind.color,
+ row[j].start, row[j].end, kExecutionFrameWidth);
+ }
+ offset = offset - 2 * kExecutionFrameWidth - kGapWidth;
+ // Javascript frames.
+ for (var i = 0; i < kStackFrames; i++) {
+ offset = offset - 2 * kStackFrameWidth - kGapWidth;
+ row = MergeRanges(code_kind.stack_frames[i]);
+ for (var j = 0; j < row.length; j++) {
+ DrawBar(offset, code_kind.color,
+ row[j].start, row[j].end, kStackFrameWidth);
+ }
}
}
+
+ // Add labels as legend for code kind colors.
+ var padding = kCodeKindLabelPadding * (xrange_end - xrange_start) /
kResX;
+ var label_x = xrange_start;
+ var label_y = kY1Offset;
+ for (var name in CodeKinds) {
+ label_x += padding;
+ print("set label \"" + name + "\" at " + label_x + "," + label_y +
+ " textcolor rgb \"" + CodeKinds[name].color + "\"" +
+ " font \"Helvetica,9'\"");
+ }
if (execution_pauses.length == 0) {
// Force plot and return without plotting execution pause impulses.
print("plot 1/0");
return;
}
-
- // Plot execution pauses as impulses. This may be better resolved
- // due to possibly smaller merge tolerance.
- if (tolerance > kPauseTolerance) {
- execution_pauses = MergeRanges(execution_pauses, kPauseTolerance);
- } else {
- execution_pauses = exclude_ranges;
- }
// Label the longest pauses.
execution_pauses.sort(
function(a, b) { return b.duration() - a.duration(); });
var max_pause_time = execution_pauses[0].duration();
- var padding = kLabelPadding * (xrange_end - xrange_start) / kResX;
- var y_scale = kY1Offset / max_pause_time;
+ padding = kPauseLabelPadding * (xrange_end - xrange_start) / kResX;
+ var y_scale = kY1Offset / max_pause_time / 2;
for (var i = 0; i < execution_pauses.length && i < kNumPauseLabels; i++)
{
var pause = execution_pauses[i];
var label_content = (pause.duration() | 0) + " ms";
@@ -316,8 +449,8 @@
}
// Scale second Y-axis appropriately.
- print("set y2range [0:" + (max_pause_time * kY2Factor) + "]");
-
+ var y2range = max_pause_time * num_timer_event / kY1Offset * 2;
+ print("set y2range [0:" + y2range + "]");
// Plot graph with impulses as data set.
print("plot '-' using 1:2 axes x1y2 with impulses ls 1");
for (var i = 0; i < execution_pauses.length; i++) {
=======================================
--- /branches/bleeding_edge/tools/tickprocessor.js Thu Nov 22 05:04:11 2012
+++ /branches/bleeding_edge/tools/tickprocessor.js Wed Nov 28 03:01:10 2012
@@ -73,7 +73,7 @@
function SnapshotLogProcessor() {
LogReader.call(this, {
'code-creation': {
- parsers: [null, parseInt, parseInt, null, 'var-args'],
+ parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
@@ -107,7 +107,7 @@
SnapshotLogProcessor.prototype.processCodeCreation = function(
- type, start, size, name, maybe_func) {
+ type, kind, start, size, name, maybe_func) {
if (maybe_func.length) {
var funcAddr = parseInt(maybe_func[0]);
var state = parseState(maybe_func[1]);
@@ -156,7 +156,7 @@
'shared-library': { parsers: [null, parseInt, parseInt],
processor: this.processSharedLibrary },
'code-creation': {
- parsers: [null, parseInt, parseInt, null, 'var-args'],
+ parsers: [null, parseInt, parseInt, parseInt, null, 'var-args'],
processor: this.processCodeCreation },
'code-move': { parsers: [parseInt, parseInt],
processor: this.processCodeMove },
@@ -167,7 +167,7 @@
'snapshot-pos': { parsers: [parseInt, parseInt],
processor: this.processSnapshotPosition },
'tick': {
- parsers: [parseInt, parseInt, parseInt,
+ parsers: [parseInt, parseInt, parseInt, parseInt,
parseInt, parseInt, 'var-args'],
processor: this.processTick },
'heap-sample-begin': { parsers: [null, null, parseInt],
@@ -309,7 +309,7 @@
TickProcessor.prototype.processCodeCreation = function(
- type, start, size, name, maybe_func) {
+ type, kind, start, size, name, maybe_func) {
name = this.deserializedEntriesNames_[start] || name;
if (maybe_func.length) {
var funcAddr = parseInt(maybe_func[0]);
@@ -350,6 +350,7 @@
TickProcessor.prototype.processTick = function(pc,
sp,
+ ns_since_start,
is_external_callback,
tos_or_external_callback,
vmState,
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev