Revision: 16109
Author: [email protected]
Date: Wed Aug 7 10:04:27 2013
Log: Support idle time in CPU profiler
This change provides an API for the embedder to tell CPU profiler if it is
idle or busy with some task. This way we can discriminate between idle time
and some native code execution.
BUG=268947
[email protected], [email protected]
Review URL: https://codereview.chromium.org/22412003
http://code.google.com/p/v8/source/detail?r=16109
Modified:
/branches/bleeding_edge/include/v8-profiler.h
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/cpu-profiler.cc
/branches/bleeding_edge/src/cpu-profiler.h
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/profile-generator-inl.h
/branches/bleeding_edge/src/profile-generator.cc
/branches/bleeding_edge/src/profile-generator.h
/branches/bleeding_edge/src/sampler.cc
/branches/bleeding_edge/src/v8globals.h
/branches/bleeding_edge/test/cctest/test-cpu-profiler.cc
/branches/bleeding_edge/test/cctest/test-log-stack-tracer.cc
/branches/bleeding_edge/tools/tickprocessor.js
=======================================
--- /branches/bleeding_edge/include/v8-profiler.h Tue Aug 6 07:37:35 2013
+++ /branches/bleeding_edge/include/v8-profiler.h Wed Aug 7 10:04:27 2013
@@ -192,6 +192,11 @@
*/
void DeleteAllCpuProfiles();
+ /**
+ * Tells the profiler whether the embedder is idle.
+ */
+ void SetIdle(bool is_idle);
+
private:
CpuProfiler();
~CpuProfiler();
=======================================
--- /branches/bleeding_edge/src/api.cc Wed Aug 7 02:33:09 2013
+++ /branches/bleeding_edge/src/api.cc Wed Aug 7 10:04:27 2013
@@ -7644,6 +7644,19 @@
void CpuProfiler::DeleteAllCpuProfiles() {
reinterpret_cast<i::CpuProfiler*>(this)->DeleteAllProfiles();
}
+
+
+void CpuProfiler::SetIdle(bool is_idle) {
+ i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
+ i::StateTag state = isolate->current_vm_state();
+ ASSERT(state == i::EXTERNAL || state == i::IDLE);
+ if (isolate->js_entry_sp() != NULL) return;
+ if (is_idle) {
+ isolate->set_current_vm_state(i::IDLE);
+ } else if (state == i::IDLE) {
+ isolate->set_current_vm_state(i::EXTERNAL);
+ }
+}
static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Tue Jul 30 00:01:16 2013
+++ /branches/bleeding_edge/src/cpu-profiler.cc Wed Aug 7 10:04:27 2013
@@ -106,7 +106,7 @@
bool ProfilerEventsProcessor::ProcessTicks() {
while (true) {
- if (!ticks_from_vm_buffer_.IsEmpty()
+ while (!ticks_from_vm_buffer_.IsEmpty()
&& ticks_from_vm_buffer_.Peek()->order ==
last_processed_code_event_id_) {
TickSampleEventRecord record;
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.h Fri Jul 26 06:50:23 2013
+++ /branches/bleeding_edge/src/cpu-profiler.h Wed Aug 7 10:04:27 2013
@@ -241,6 +241,7 @@
ProfileGenerator* generator() const { return generator_; }
ProfilerEventsProcessor* processor() const { return processor_; }
+ Isolate* isolate() const { return isolate_; }
private:
void StartProcessorIfNotStarted();
@@ -258,7 +259,6 @@
bool need_to_stop_sampler_;
bool is_profiling_;
- private:
DISALLOW_COPY_AND_ASSIGN(CpuProfiler);
};
=======================================
--- /branches/bleeding_edge/src/isolate.h Wed Aug 7 02:33:09 2013
+++ /branches/bleeding_edge/src/isolate.h Wed Aug 7 10:04:27 2013
@@ -661,9 +661,9 @@
}
inline Address* handler_address() { return &thread_local_top_.handler_; }
- // Bottom JS entry (see StackTracer::Trace in sampler.cc).
- static Address js_entry_sp(ThreadLocalTop* thread) {
- return thread->js_entry_sp_;
+ // Bottom JS entry.
+ Address js_entry_sp() {
+ return thread_local_top_.js_entry_sp_;
}
inline Address* js_entry_sp_address() {
return &thread_local_top_.js_entry_sp_;
=======================================
--- /branches/bleeding_edge/src/profile-generator-inl.h Sat Jul 6 02:12:09
2013
+++ /branches/bleeding_edge/src/profile-generator-inl.h Wed Aug 7 10:04:27
2013
@@ -92,6 +92,8 @@
case OTHER:
case EXTERNAL:
return program_entry_;
+ case IDLE:
+ return idle_entry_;
default: return NULL;
}
}
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Aug 6 01:00:58
2013
+++ /branches/bleeding_edge/src/profile-generator.cc Wed Aug 7 10:04:27
2013
@@ -614,6 +614,8 @@
"(anonymous function)";
const char* const ProfileGenerator::kProgramEntryName =
"(program)";
+const char* const ProfileGenerator::kIdleEntryName =
+ "(idle)";
const char* const ProfileGenerator::kGarbageCollectorEntryName =
"(garbage collector)";
const char* const ProfileGenerator::kUnresolvedFunctionName =
@@ -624,6 +626,8 @@
: profiles_(profiles),
program_entry_(
profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
+ idle_entry_(
+ profiles->NewCodeEntry(Logger::FUNCTION_TAG, kIdleEntryName)),
gc_entry_(
profiles->NewCodeEntry(Logger::BUILTIN_TAG,
kGarbageCollectorEntryName)),
=======================================
--- /branches/bleeding_edge/src/profile-generator.h Tue Aug 6 01:00:58 2013
+++ /branches/bleeding_edge/src/profile-generator.h Wed Aug 7 10:04:27 2013
@@ -342,6 +342,7 @@
static const char* const kAnonymousFunctionName;
static const char* const kProgramEntryName;
+ static const char* const kIdleEntryName;
static const char* const kGarbageCollectorEntryName;
// Used to represent frames for which we have no reliable way to
// detect function.
@@ -353,6 +354,7 @@
CpuProfilesCollection* profiles_;
CodeMap code_map_;
CodeEntry* program_entry_;
+ CodeEntry* idle_entry_;
CodeEntry* gc_entry_;
CodeEntry* unresolved_entry_;
=======================================
--- /branches/bleeding_edge/src/sampler.cc Wed Jul 31 00:51:46 2013
+++ /branches/bleeding_edge/src/sampler.cc Wed Aug 7 10:04:27 2013
@@ -615,8 +615,7 @@
// Avoid collecting traces while doing GC.
if (state == GC) return;
- const Address js_entry_sp =
- Isolate::js_entry_sp(isolate->thread_local_top());
+ Address js_entry_sp = isolate->js_entry_sp();
if (js_entry_sp == 0) {
// Not executing JS now.
return;
=======================================
--- /branches/bleeding_edge/src/v8globals.h Wed Jul 10 08:32:39 2013
+++ /branches/bleeding_edge/src/v8globals.h Wed Aug 7 10:04:27 2013
@@ -363,7 +363,8 @@
GC,
COMPILER,
OTHER,
- EXTERNAL
+ EXTERNAL,
+ IDLE
};
=======================================
--- /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Tue Aug 6
01:00:58 2013
+++ /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Wed Aug 7
10:04:27 2013
@@ -1324,3 +1324,56 @@
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
cpu_profiler->DeleteAllCpuProfiles();
}
+
+
+// [Top down]:
+// 6 0 (root) #0 1
+// 3 3 (program) #0 2
+// 3 3 (idle) #0 3
+TEST(IdleTime) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+ cpu_profiler->StartCpuProfiling(profile_name);
+
+ i::Isolate* isolate = i::Isolate::Current();
+ i::ProfilerEventsProcessor* processor =
isolate->cpu_profiler()->processor();
+ processor->AddCurrentStack(isolate);
+
+ cpu_profiler->SetIdle(true);
+
+ for (int i = 0; i < 3; i++) {
+ processor->AddCurrentStack(isolate);
+ }
+
+ cpu_profiler->SetIdle(false);
+ processor->AddCurrentStack(isolate);
+
+
+ const v8::CpuProfile* profile =
cpu_profiler->StopCpuProfiling(profile_name);
+ CHECK_NE(NULL, profile);
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ ScopedVector<v8::Handle<v8::String> > names(3);
+ names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::New(ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::New(ProfileGenerator::kIdleEntryName);
+ CheckChildrenNames(root, names);
+
+ const v8::CpuProfileNode* programNode =
+ GetChild(root, ProfileGenerator::kProgramEntryName);
+ CHECK_EQ(0, programNode->GetChildrenCount());
+ CHECK_GE(programNode->GetSelfSamplesCount(), 3);
+
+ const v8::CpuProfileNode* idleNode =
+ GetChild(root, ProfileGenerator::kIdleEntryName);
+ CHECK_EQ(0, idleNode->GetChildrenCount());
+ CHECK_GE(idleNode->GetSelfSamplesCount(), 3);
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
=======================================
--- /branches/bleeding_edge/test/cctest/test-log-stack-tracer.cc Fri Jul 5
02:52:11 2013
+++ /branches/bleeding_edge/test/cctest/test-log-stack-tracer.cc Wed Aug 7
10:04:27 2013
@@ -157,7 +157,7 @@
static Address GetJsEntrySp() {
CHECK_NE(NULL, i::Isolate::Current()->thread_local_top());
- return Isolate::js_entry_sp(i::Isolate::Current()->thread_local_top());
+ return i::Isolate::Current()->js_entry_sp();
}
=======================================
--- /branches/bleeding_edge/tools/tickprocessor.js Wed Jul 3 09:20:59 2013
+++ /branches/bleeding_edge/tools/tickprocessor.js Wed Aug 7 10:04:27 2013
@@ -249,7 +249,8 @@
GC: 1,
COMPILER: 2,
OTHER: 3,
- EXTERNAL: 4
+ EXTERNAL: 4,
+ IDLE: 5
};
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.