Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Unified Diff: runtime/vm/profiler.cc

Issue 168833005: Add callers and callees to profiler output (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/profiler.cc
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index e8f484e50f5b0fa0a7b9251b07292ade28d64b6f..2e8910c15810319c6e740e346fcb45ac5069c4a3 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -162,7 +162,21 @@ void Profiler::EndExecution(Isolate* isolate) {
struct AddressEntry {
uword pc;
- intptr_t ticks;
+ intptr_t exclusive_ticks;
+ intptr_t inclusive_ticks;
+
+ void tick(bool exclusive) {
+ if (exclusive) {
+ exclusive_ticks++;
+ } else {
+ inclusive_ticks++;
+ }
+ }
+};
+
+struct CallEntry {
+ intptr_t code_table_index;
+ intptr_t count;
};
typedef bool (*RegionCompare)(uword pc, uword region_start, uword region_end);
@@ -183,7 +197,9 @@ class CodeRegion : public ZoneAllocated {
inclusive_ticks_(0),
exclusive_ticks_(0),
name_(NULL),
- address_table_(new ZoneGrowableArray<AddressEntry>()) {
+ address_table_(new ZoneGrowableArray<AddressEntry>()),
+ callers_table_(new ZoneGrowableArray<CallEntry>()),
+ callees_table_(new ZoneGrowableArray<CallEntry>()) {
ASSERT(start_ < end_);
}
@@ -258,26 +274,25 @@ class CodeRegion : public ZoneAllocated {
return NULL;
}
- void AddTick(bool exclusive) {
- if (exclusive) {
- exclusive_ticks_++;
- } else {
- inclusive_ticks_++;
- }
- }
-
void DebugPrint() const {
printf("%s [%" Px ", %" Px ") %s\n", KindToCString(kind_), start(), end(),
name_);
}
- void AddTickAtAddress(uword pc) {
+ void AddTickAtAddress(uword pc, bool exclusive) {
+ // Tick the code object.
+ if (exclusive) {
+ exclusive_ticks_++;
+ } else {
+ inclusive_ticks_++;
+ }
+ // Tick the address entry.
const intptr_t length = address_table_->length();
intptr_t i = 0;
for (; i < length; i++) {
AddressEntry& entry = (*address_table_)[i];
if (entry.pc == pc) {
- entry.ticks++;
+ entry.tick(exclusive);
return;
}
if (entry.pc > pc) {
@@ -286,7 +301,7 @@ class CodeRegion : public ZoneAllocated {
}
AddressEntry entry;
entry.pc = pc;
- entry.ticks = 1;
+ entry.tick(exclusive);
if (i < length) {
// Insert at i.
address_table_->InsertAt(i, entry);
@@ -296,6 +311,51 @@ class CodeRegion : public ZoneAllocated {
}
}
+ void AddCaller(intptr_t index) {
+ const intptr_t length = callers_table_->length();
+ intptr_t i = 0;
+ for (; i < length; i++) {
+ CallEntry& entry = (*callers_table_)[i];
+ if (entry.code_table_index == index) {
+ entry.count++;
+ return;
+ }
+ if (entry.code_table_index > index) {
+ break;
+ }
+ }
+ CallEntry entry;
+ entry.code_table_index = index;
+ entry.count = 1;
+ if (i < length) {
+ callers_table_->InsertAt(i, entry);
+ } else {
+ callers_table_->Add(entry);
+ }
+ }
+
+ void AddCallee(intptr_t index) {
+ const intptr_t length = callees_table_->length();
+ intptr_t i = 0;
+ for (; i < length; i++) {
+ CallEntry& entry = (*callees_table_)[i];
+ if (entry.code_table_index == index) {
+ entry.count++;
+ return;
+ }
+ if (entry.code_table_index > index) {
+ break;
+ }
+ }
+ CallEntry entry;
+ entry.code_table_index = index;
+ entry.count = 1;
+ if (i < length) {
+ callees_table_->InsertAt(i, entry);
+ } else {
+ callees_table_->Add(entry);
+ }
+ }
siva 2014/02/21 22:23:48 These two functions are identical except for the t
Cutch 2014/02/24 15:18:56 Done.
void PrintToJSONArray(JSONArray* events, bool full) {
JSONObject obj(events);
@@ -340,7 +400,24 @@ class CodeRegion : public ZoneAllocated {
for (intptr_t i = 0; i < address_table_->length(); i++) {
const AddressEntry& entry = (*address_table_)[i];
ticks.AddValueF("%" Px "", entry.pc);
- ticks.AddValueF("%" Pd "", entry.ticks);
+ ticks.AddValueF("%" Pd "", entry.exclusive_ticks);
+ ticks.AddValueF("%" Pd "", entry.inclusive_ticks);
+ }
+ }
+ {
+ JSONArray callers(&obj, "callers");
+ for (intptr_t i = 0; i < callers_table_->length(); i++) {
+ const CallEntry& entry = (*callers_table_)[i];
+ callers.AddValueF("%" Pd "", entry.code_table_index);
+ callers.AddValueF("%" Pd "", entry.count);
+ }
+ }
+ {
+ JSONArray callers(&obj, "callees");
siva 2014/02/21 22:23:48 name the variable callees instead of callers to ma
Cutch 2014/02/24 15:18:56 Done.
+ for (intptr_t i = 0; i < callees_table_->length(); i++) {
+ const CallEntry& entry = (*callees_table_)[i];
+ callers.AddValueF("%" Pd "", entry.code_table_index);
+ callers.AddValueF("%" Pd "", entry.count);
}
}
}
@@ -361,7 +438,8 @@ class CodeRegion : public ZoneAllocated {
intptr_t exclusive_ticks_;
const char* name_;
ZoneGrowableArray<AddressEntry>* address_table_;
-
+ ZoneGrowableArray<CallEntry>* callers_table_;
+ ZoneGrowableArray<CallEntry>* callees_table_;
DISALLOW_COPY_AND_ASSIGN(CodeRegion);
};
@@ -396,6 +474,8 @@ class ScopeStopwatch : public ValueObject {
class ProfilerCodeRegionTable : public ValueObject {
public:
explicit ProfilerCodeRegionTable(Isolate* isolate) :
+ inclusive_ticks_(0),
+ exclusive_ticks_(0),
heap_(isolate->heap()),
code_region_table_(new ZoneGrowableArray<CodeRegion*>(64)) {
}
@@ -403,7 +483,7 @@ class ProfilerCodeRegionTable : public ValueObject {
~ProfilerCodeRegionTable() {
}
- void AddTick(uword pc, bool exclusive, bool tick_address) {
+ void AddTick(uword pc, bool exclusive) {
intptr_t index = FindIndex(pc);
if (index < 0) {
CodeRegion* code_region = CreateCodeRegion(pc);
@@ -412,10 +492,16 @@ class ProfilerCodeRegionTable : public ValueObject {
}
ASSERT(index >= 0);
ASSERT(index < code_region_table_->length());
- (*code_region_table_)[index]->AddTick(exclusive);
- if (tick_address) {
- (*code_region_table_)[index]->AddTickAtAddress(pc);
+
+ // Update global counters.
+ if (exclusive) {
+ exclusive_ticks_++;
+ } else {
+ inclusive_ticks_++;
}
+
+ // Update code object counters.
+ (*code_region_table_)[index]->AddTickAtAddress(pc, exclusive);
}
intptr_t Length() const { return code_region_table_->length(); }
@@ -424,6 +510,25 @@ class ProfilerCodeRegionTable : public ValueObject {
return (*code_region_table_)[idx];
}
+ intptr_t exclusive_ticks() const { return exclusive_ticks_; }
+
+ intptr_t inclusive_ticks() const { return inclusive_ticks_; }
+
+ intptr_t FindIndex(uword pc) {
siva 2014/02/21 22:23:48 const function too?
Cutch 2014/02/24 15:18:56 Done.
+ intptr_t index = FindRegionIndex(pc, &CompareLowerBound);
+ const CodeRegion* code_region = NULL;
+ if (index == code_region_table_->length()) {
+ // Not present.
+ return -1;
+ }
+ code_region = (*code_region_table_)[index];
+ if (code_region->contains(pc)) {
+ // Found at index.
+ return index;
+ }
+ return -1;
+ }
+
#if defined(DEBUG)
void Verify() {
VerifyOrder();
@@ -459,21 +564,6 @@ class ProfilerCodeRegionTable : public ValueObject {
return end <= pc;
}
- intptr_t FindIndex(uword pc) {
- intptr_t index = FindRegionIndex(pc, &CompareLowerBound);
- const CodeRegion* code_region = NULL;
- if (index == code_region_table_->length()) {
- // Not present.
- return -1;
- }
- code_region = (*code_region_table_)[index];
- if (code_region->contains(pc)) {
- // Found at index.
- return index;
- }
- return -1;
- }
-
CodeRegion* CreateCodeRegion(uword pc) {
Code& code = Code::Handle(Code::LookupCode(pc));
if (!code.IsNull()) {
@@ -593,6 +683,8 @@ class ProfilerCodeRegionTable : public ValueObject {
}
#endif
+ intptr_t inclusive_ticks_;
+ intptr_t exclusive_ticks_;
Heap* heap_;
ZoneGrowableArray<CodeRegion*>* code_region_table_;
};
@@ -607,24 +699,65 @@ class CodeRegionTableBuilder : public SampleVisitor {
}
void VisitSample(Sample* sample) {
- code_region_table_->AddTick(sample->At(0), true, false);
- // Give all frames an inclusive tick and tick the address.
+ // Give the bottom frame an exclusive tick.
+ code_region_table_->AddTick(sample->At(0), true);
+ // Give all frames (including the bottom) an inclusive tick.
for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
if (sample->At(i) == 0) {
break;
}
frames_++;
- code_region_table_->AddTick(sample->At(i), false, true);
+ code_region_table_->AddTick(sample->At(i), false);
}
}
intptr_t frames() const { return frames_; }
+
private:
intptr_t frames_;
ProfilerCodeRegionTable* code_region_table_;
};
+class CodeRegionTableCallersBuilder : public SampleVisitor {
+ public:
+ CodeRegionTableCallersBuilder(Isolate* isolate,
+ ProfilerCodeRegionTable* code_region_table)
+ : SampleVisitor(isolate), code_region_table_(code_region_table) {
+ ASSERT(code_region_table_ != NULL);
+ }
+
+ void VisitSample(Sample* sample) {
+ intptr_t current_index = code_region_table_->FindIndex(sample->At(0));
+ ASSERT(current_index != -1);
+ CodeRegion* current = code_region_table_->At(current_index);
+ intptr_t caller_index = -1;
+ CodeRegion* caller = NULL;
+ intptr_t callee_index = -1;
+ CodeRegion* callee = NULL;
+ for (intptr_t i = 1; i < FLAG_profile_depth; i++) {
+ if (sample->At(i) == 0) {
+ break;
+ }
+ caller_index = code_region_table_->FindIndex(sample->At(i));
+ ASSERT(caller_index != -1);
+ caller = code_region_table_->At(caller_index);
+ current->AddCaller(caller_index);
+ if (callee != NULL) {
+ current->AddCallee(callee_index);
+ }
+ // Move cursors.
+ callee_index = current_index;
+ callee = current;
+ current_index = caller_index;
+ current = caller;
+ }
+ }
+
+ private:
+ ProfilerCodeRegionTable* code_region_table_;
+};
+
void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
bool full) {
ASSERT(isolate == Isolate::Current());
@@ -646,6 +779,7 @@ void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
// Build code region table.
ProfilerCodeRegionTable code_region_table(isolate);
CodeRegionTableBuilder builder(isolate, &code_region_table);
+ CodeRegionTableCallersBuilder build_callers(isolate, &code_region_table);
{
ScopeStopwatch sw("CodeTableBuild");
sample_buffer->VisitSamples(&builder);
@@ -653,8 +787,11 @@ void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
#if defined(DEBUG)
code_region_table.Verify();
#endif
+ {
+ ScopeStopwatch sw("CodeTableCallersBuild");
+ sample_buffer->VisitSamples(&build_callers);
+ }
// Number of samples we processed.
- intptr_t samples = builder.visited();
intptr_t frames = builder.frames();
if (FLAG_trace_profiled_isolates) {
OS::Print("%" Pd " frames produced %" Pd " code objects.\n",
@@ -665,7 +802,8 @@ void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream,
// Serialize to JSON.
JSONObject obj(stream);
obj.AddProperty("type", "Profile");
- obj.AddProperty("samples", samples);
+ obj.AddProperty("exclusive_ticks", code_region_table.exclusive_ticks());
+ obj.AddProperty("inclusive_ticks", code_region_table.inclusive_ticks());
JSONArray codes(&obj, "codes");
for (intptr_t i = 0; i < code_region_table.Length(); i++) {
CodeRegion* region = code_region_table.At(i);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698