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

Unified Diff: runtime/vm/profiler.cc

Issue 131853007: Add flag to control number of stack frames collected by profiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 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 | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_test.cc » ('j') | 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 b967123466e3ff9856cd092bebba57885d70df56..34035e0dd45b7009a7f8be676d075b0e77d4238d 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -19,15 +19,6 @@
namespace dart {
-// Notes on stack frame walking:
-//
-// The sampling profiler will collect up to Sample::kNumStackFrames stack frames
-// The stack frame walking code uses the frame pointer to traverse the stack.
-// If the VM is compiled without frame pointers (which is the default on
-// recent GCC versions with optimizing enabled) the stack walking code may
-// fail (sometimes leading to a crash).
-//
-
#if defined(USING_SIMULATOR) || defined(TARGET_OS_WINDOWS) || \
defined(TARGET_OS_MACOS) || defined(TARGET_OS_ANDROID)
DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
@@ -39,26 +30,35 @@ DEFINE_FLAG(charp, profile_dir, NULL,
"Enable writing profile data into specified directory.");
DEFINE_FLAG(int, profile_period, 1000,
"Time between profiler samples in microseconds. Minimum 250.");
+DEFINE_FLAG(int, profile_depth, 8,
+ "Maximum number stack frames walked. Minimum 1. Maximum 128.");
bool Profiler::initialized_ = false;
-Monitor* Profiler::monitor_ = NULL;
SampleBuffer* Profiler::sample_buffer_ = NULL;
void Profiler::InitOnce() {
const int kMinimumProfilePeriod = 250;
+ const int kMinimumDepth = 1;
+ const int kMaximumDepth = 128;
if (!FLAG_profile) {
return;
}
ASSERT(!initialized_);
- initialized_ = true;
- monitor_ = new Monitor();
- sample_buffer_ = new SampleBuffer();
- NativeSymbolResolver::InitOnce();
- ThreadInterrupter::InitOnce();
+ // Place some sane restrictions on user controlled flags.
if (FLAG_profile_period < kMinimumProfilePeriod) {
FLAG_profile_period = kMinimumProfilePeriod;
}
+ if (FLAG_profile_depth < kMinimumDepth) {
+ FLAG_profile_depth = kMinimumDepth;
+ } else if (FLAG_profile_depth > kMaximumDepth) {
+ FLAG_profile_depth = kMaximumDepth;
+ }
+ Sample::InitOnce();
+ sample_buffer_ = new SampleBuffer();
+ NativeSymbolResolver::InitOnce();
+ ThreadInterrupter::InitOnce();
ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
+ initialized_ = true;
}
@@ -78,7 +78,6 @@ void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
}
ASSERT(isolate != NULL);
ASSERT(sample_buffer_ != NULL);
- MonitorLocker ml(monitor_);
{
MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
SampleBuffer* sample_buffer = sample_buffer_;
@@ -103,7 +102,6 @@ void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) {
}
// We do not have a current isolate.
ASSERT(Isolate::Current() == NULL);
- MonitorLocker ml(monitor_);
{
MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
@@ -540,16 +538,18 @@ intptr_t Profiler::ProcessSamples(Isolate* isolate,
SampleBuffer* sample_buffer) {
int64_t start = OS::GetCurrentTimeMillis();
intptr_t samples = 0;
+ Sample* sample = Sample::Allocate();
for (intptr_t i = 0; i < sample_buffer->capacity(); i++) {
- Sample sample = sample_buffer->GetSample(i);
- if (sample.isolate != isolate) {
+ sample_buffer->CopySample(i, sample);
+ if (sample->isolate() != isolate) {
continue;
}
- if (sample.timestamp == 0) {
+ if (sample->timestamp() == 0) {
continue;
}
- samples += ProcessSample(isolate, code_region_table, &sample);
+ samples += ProcessSample(isolate, code_region_table, sample);
}
+ free(sample);
int64_t end = OS::GetCurrentTimeMillis();
if (FLAG_trace_profiled_isolates) {
int64_t delta = end - start;
@@ -565,23 +565,21 @@ intptr_t Profiler::ProcessSamples(Isolate* isolate,
intptr_t Profiler::ProcessSample(Isolate* isolate,
ProfilerCodeRegionTable* code_region_table,
Sample* sample) {
- Sample::SampleType type = sample->type;
- if (type != Sample::kIsolateSample) {
+ if (sample->type() != Sample::kIsolateSample) {
return 0;
}
- if (sample->pcs[0] == 0) {
+ if (sample->At(0) == 0) {
// No frames in this sample.
return 0;
}
- intptr_t i = 0;
// i points to the leaf (exclusive) PC sample. Do not tick the address.
- code_region_table->AddTick(sample->pcs[i], true, false);
+ code_region_table->AddTick(sample->At(0), true, false);
// Give all frames an inclusive tick and tick the address.
- for (; i < Sample::kNumStackFrames; i++) {
- if (sample->pcs[i] == 0) {
+ for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
+ if (sample->At(i) == 0) {
break;
}
- code_region_table->AddTick(sample->pcs[i], false, true);
+ code_region_table->AddTick(sample->At(i), false, true);
}
return 1;
}
@@ -645,22 +643,62 @@ IsolateProfilerData::~IsolateProfilerData() {
}
+intptr_t Sample::instance_size_ = 0;
+
+void Sample::InitOnce() {
+ ASSERT(FLAG_profile_depth >= 1);
+ instance_size_ =
+ sizeof(Sample) + (sizeof(intptr_t) * FLAG_profile_depth); // NOLINT.
+}
+
+
+uintptr_t Sample::At(intptr_t i) const {
+ ASSERT(i >= 0);
+ ASSERT(i < FLAG_profile_depth);
+ return pcs_[i];
+}
+
+
+void Sample::SetAt(intptr_t i, uintptr_t pc) {
+ ASSERT(i >= 0);
+ ASSERT(i < FLAG_profile_depth);
+ pcs_[i] = pc;
+}
+
+
void Sample::Init(SampleType type, Isolate* isolate, int64_t timestamp,
ThreadId tid) {
- this->timestamp = timestamp;
- this->tid = tid;
- this->isolate = isolate;
- for (intptr_t i = 0; i < kNumStackFrames; i++) {
- pcs[i] = 0;
- }
- this->type = type;
- vm_tags = 0;
- runtime_tags = 0;
+ timestamp_ = timestamp;
+ tid_ = tid;
+ isolate_ = isolate;
+ type_ = type;
+ for (int i = 0; i < FLAG_profile_depth; i++) {
+ pcs_[i] = 0;
+ }
}
+
+void Sample::CopyInto(Sample* dst) const {
+ ASSERT(dst != NULL);
+ dst->timestamp_ = timestamp_;
+ dst->tid_ = tid_;
+ dst->isolate_ = isolate_;
+ dst->type_ = type_;
+ for (intptr_t i = 0; i < FLAG_profile_depth; i++) {
+ dst->pcs_[i] = pcs_[i];
+ }
+}
+
+
+Sample* Sample::Allocate() {
+ return reinterpret_cast<Sample*>(malloc(instance_size()));
+}
+
+
SampleBuffer::SampleBuffer(intptr_t capacity) {
capacity_ = capacity;
- samples_ = reinterpret_cast<Sample*>(calloc(capacity, sizeof(Sample)));
+ samples_ = reinterpret_cast<Sample*>(
+ calloc(capacity, Sample::instance_size()));
cursor_ = 0;
}
@@ -680,7 +718,21 @@ Sample* SampleBuffer::ReserveSample() {
uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
// Map back into sample buffer range.
cursor = cursor % capacity_;
- return &samples_[cursor];
+ return At(cursor);
+}
+
+
+void SampleBuffer::CopySample(intptr_t i, Sample* sample) const {
+ At(i)->CopyInto(sample);
+}
+
+
+Sample* SampleBuffer::At(intptr_t idx) const {
+ ASSERT(idx >= 0);
+ ASSERT(idx < capacity_);
+ intptr_t offset = idx * Sample::instance_size();
+ uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
+ return reinterpret_cast<Sample*>(samples + offset);
}
@@ -698,20 +750,28 @@ ProfilerSampleStackWalker::ProfilerSampleStackWalker(Sample* sample,
original_sp_(sp),
lower_bound_(stack_lower) {
ASSERT(sample_ != NULL);
- // Zero out the PCs before (re)using the sample.
- for (int i = 0; i < Sample::kNumStackFrames; i++) {
- sample_->pcs[i] = 0;
- }
}
+// Notes on stack frame walking:
+//
+// The sampling profiler will collect up to Sample::kNumStackFrames stack frames
+// The stack frame walking code uses the frame pointer to traverse the stack.
+// If the VM is compiled without frame pointers (which is the default on
+// recent GCC versions with optimizing enabled) the stack walking code may
+// fail (sometimes leading to a crash).
+//
+
int ProfilerSampleStackWalker::walk() {
const intptr_t kMaxStep = 0x1000; // 4K.
- uword* pc = reinterpret_cast<uword*>(original_pc_);
+ const bool kWalkStack = true; // Walk the stack.
// Always store the exclusive PC.
- sample_->pcs[0] = original_pc_;
-#define WALK_STACK
-#if defined(WALK_STACK)
+ sample_->SetAt(0, original_pc_);
+ if (!kWalkStack) {
+ // Not walking the stack, only took exclusive sample.
+ return 1;
+ }
+ uword* pc = reinterpret_cast<uword*>(original_pc_);
uword* fp = reinterpret_cast<uword*>(original_fp_);
uword* previous_fp = fp;
if (original_sp_ > original_fp_) {
@@ -730,8 +790,8 @@ int ProfilerSampleStackWalker::walk() {
lower_bound_ = original_sp_;
}
int i = 0;
- for (; i < Sample::kNumStackFrames; i++) {
- sample_->pcs[i] = reinterpret_cast<uintptr_t>(pc);
+ for (; i < FLAG_profile_depth; i++) {
+ sample_->SetAt(i, reinterpret_cast<uintptr_t>(pc));
if (!ValidFramePointer(fp)) {
return i + 1;
}
@@ -749,10 +809,6 @@ int ProfilerSampleStackWalker::walk() {
lower_bound_ = reinterpret_cast<uintptr_t>(fp);
}
return i;
-#else
- sample_->pcs[0] = reinterpret_cast<uintptr_t>(pc);
- return 0;
-#endif
}
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698