Reviewers: yurys, loislo, Benedikt Meurer,
Message:
Folks, could you please take a look.
Description:
Add timestamps to CPU profile samples.
BUG=363976
LOG=Y
Please review this at https://codereview.chromium.org/259803002/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+74, -22 lines):
M include/v8-profiler.h
M src/api.cc
M src/profile-generator.h
M src/profile-generator.cc
M src/sampler.h
M src/sampler.cc
M test/cctest/test-cpu-profiler.cc
Index: include/v8-profiler.h
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index
026715fda785463d8c743313576ac8bfcadce29d..483fd933f8c2150e1f6521eaca4f5b1979504001
100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -106,28 +106,35 @@ class V8_EXPORT CpuProfile {
const CpuProfileNode* GetTopDownRoot() const;
/**
- * Returns number of samples recorded. The samples are not recorded
unless
- * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
- */
+ * Returns number of samples recorded. The samples are not recorded
unless
+ * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
+ */
int GetSamplesCount() const;
/**
- * Returns profile node corresponding to the top frame the sample at
- * the given index.
- */
+ * Returns profile node corresponding to the top frame the sample at
+ * the given index.
+ */
const CpuProfileNode* GetSample(int index) const;
/**
- * Returns time when the profile recording was started (in microseconds)
- * since some unspecified starting point.
- */
+ * Returns the timestamp of the sample. The timestamp is the number of
+ * microseconds since some unspecified starting point.
+ * The point is equal to the starting point used by GetStartTime.
+ */
+ int64_t GetSampleTimestamp(int index) const;
+
+ /**
+ * Returns time when the profile recording was started (in microseconds)
+ * since some unspecified starting point.
+ */
int64_t GetStartTime() const;
/**
- * Returns time when the profile recording was stopped (in microseconds)
- * since some unspecified starting point. The point is however equal to
the
- * starting point used by GetStartTime.
- */
+ * Returns time when the profile recording was stopped (in microseconds)
+ * since some unspecified starting point.
+ * The point is equal to the starting point used by GetStartTime.
+ */
int64_t GetEndTime() const;
/**
Index: src/api.cc
diff --git a/src/api.cc b/src/api.cc
index
705cae55b00b4afb3bec52ed087f8b2f493f9e32..3af59e9380dd9dbde927c9c0b5b7dd94a1598e71
100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -7083,6 +7083,12 @@ const CpuProfileNode* CpuProfile::GetSample(int
index) const {
}
+int64_t CpuProfile::GetSampleTimestamp(int index) const {
+ const i::CpuProfile* profile = reinterpret_cast<const
i::CpuProfile*>(this);
+ return (profile->sample_timestamp(index) -
i::TimeTicks()).InMicroseconds();
+}
+
+
int64_t CpuProfile::GetStartTime() const {
const i::CpuProfile* profile = reinterpret_cast<const
i::CpuProfile*>(this);
return (profile->start_time() - i::TimeTicks()).InMicroseconds();
Index: src/profile-generator.cc
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index
ae37648e5ea99cb1cf754cbafb56c5f020575ce1..2587317c8ae09639323e62995108a74e5d74875c
100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -359,9 +359,12 @@ CpuProfile::CpuProfile(const char* title, bool
record_samples)
}
-void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
+void CpuProfile::AddPath(TimeTicks timestamp, const Vector<CodeEntry*>&
path) {
ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path);
- if (record_samples_) samples_.Add(top_frame_node);
+ if (record_samples_) {
+ timestamps_.Add(timestamp);
+ samples_.Add(top_frame_node);
+ }
}
@@ -545,13 +548,13 @@ void CpuProfilesCollection::RemoveProfile(CpuProfile*
profile) {
void CpuProfilesCollection::AddPathToCurrentProfiles(
- const Vector<CodeEntry*>& path) {
+ TimeTicks timestamp, const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
// method, we don't bother minimizing the duration of lock holding,
// e.g. copying contents of the list to a local vector.
current_profiles_semaphore_.Wait();
for (int i = 0; i < current_profiles_.length(); ++i) {
- current_profiles_[i]->AddPath(path);
+ current_profiles_[i]->AddPath(timestamp, path);
}
current_profiles_semaphore_.Signal();
}
@@ -674,7 +677,7 @@ void ProfileGenerator::RecordTickSample(const
TickSample& sample) {
}
}
- profiles_->AddPathToCurrentProfiles(entries);
+ profiles_->AddPathToCurrentProfiles(sample.timestamp, entries);
}
Index: src/profile-generator.h
diff --git a/src/profile-generator.h b/src/profile-generator.h
index
1f23ee20ffe5bf8827bb28de6800568814a02b61..52636507038ab0a609f92d25e39a7b23fcb12f00
100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -199,7 +199,7 @@ class CpuProfile {
CpuProfile(const char* title, bool record_samples);
// Add pc -> ... -> main() call path to the profile.
- void AddPath(const Vector<CodeEntry*>& path);
+ void AddPath(TimeTicks timestamp, const Vector<CodeEntry*>& path);
void CalculateTotalTicksAndSamplingRate();
const char* title() const { return title_; }
@@ -207,6 +207,7 @@ class CpuProfile {
int samples_count() const { return samples_.length(); }
ProfileNode* sample(int index) const { return samples_.at(index); }
+ TimeTicks sample_timestamp(int index) const { return
timestamps_.at(index); }
TimeTicks start_time() const { return start_time_; }
TimeTicks end_time() const { return end_time_; }
@@ -221,6 +222,7 @@ class CpuProfile {
TimeTicks start_time_;
TimeTicks end_time_;
List<ProfileNode*> samples_;
+ List<TimeTicks> timestamps_;
ProfileTree top_down_;
DISALLOW_COPY_AND_ASSIGN(CpuProfile);
@@ -305,7 +307,8 @@ class CpuProfilesCollection {
int column_number = v8::CpuProfileNode::kNoColumnNumberInfo);
// Called from profile generator thread.
- void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
+ void AddPathToCurrentProfiles(
+ TimeTicks timestamp, const Vector<CodeEntry*>& path);
// Limits the number of profiles that can be simultaneously collected.
static const int kMaxSimultaneousProfiles = 100;
Index: src/sampler.cc
diff --git a/src/sampler.cc b/src/sampler.cc
index
c6830e69047612a5d7a3f73a255c9114cdce4df1..bb1935bddfd2436dd7e4e82965ed4d838136a05f
100644
--- a/src/sampler.cc
+++ b/src/sampler.cc
@@ -589,6 +589,7 @@ SamplerThread* SamplerThread::instance_ = NULL;
DISABLE_ASAN void TickSample::Init(Isolate* isolate,
const RegisterState& regs) {
ASSERT(isolate->IsInitialized());
+ timestamp = TimeTicks::HighResolutionNow();
pc = regs.pc;
state = isolate->current_vm_state();
Index: src/sampler.h
diff --git a/src/sampler.h b/src/sampler.h
index
b17a2ed8d50e383c5a16da4c56f085464402a512..a051e257b65a432f06fdd9518c1f17bd28eb1b34
100644
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -69,6 +69,7 @@ struct TickSample {
};
static const int kMaxFramesCount = 64;
Address stack[kMaxFramesCount]; // Call stack.
+ TimeTicks timestamp;
int frames_count : 8; // Number of captured frames.
bool has_external_callback : 1;
StackFrame::Type top_frame_type : 4;
Index: test/cctest/test-cpu-profiler.cc
diff --git a/test/cctest/test-cpu-profiler.cc
b/test/cctest/test-cpu-profiler.cc
index
d3fcf7d7edee3ea842834152a547c9618bdab92e..6cff7424b7bf7bb8fcd79e4400da66baec0861c7
100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -401,12 +401,12 @@ TEST(ProfileStartEndTime) {
static v8::CpuProfile* RunProfiler(
v8::Handle<v8::Context> env, v8::Handle<v8::Function> function,
v8::Handle<v8::Value> argv[], int argc,
- unsigned min_js_samples) {
+ unsigned min_js_samples, bool collect_samples = false) {
v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
v8::Local<v8::String> profile_name =
v8::String::NewFromUtf8(env->GetIsolate(), "my_profile");
- cpu_profiler->StartProfiling(profile_name);
+ cpu_profiler->StartProfiling(profile_name, collect_samples);
i::Sampler* sampler =
reinterpret_cast<i::Isolate*>(env->GetIsolate())->logger()->sampler();
@@ -587,6 +587,37 @@ TEST(CollectCpuProfile) {
}
+TEST(CollectCpuProfileSamples) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
+
cpu_profiler_test_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "start")));
+
+ int32_t profiling_interval_ms = 200;
+ v8::Handle<v8::Value> args[] = {
+ v8::Integer::New(env->GetIsolate(), profiling_interval_ms)
+ };
+ v8::CpuProfile* profile =
+ RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200,
true);
+
+ CHECK_LE(200, profile->GetSamplesCount());
+ uint64_t end_time = profile->GetEndTime();
+ uint64_t current_time = profile->GetStartTime();
+ CHECK_LE(current_time, end_time);
+ for (int i = 0; i < profile->GetSamplesCount(); i++) {
+ CHECK_NE(NULL, profile->GetSample(i));
+ uint64_t timestamp = profile->GetSampleTimestamp(i);
+ CHECK_LE(current_time, timestamp);
+ CHECK_LE(timestamp, end_time);
+ current_time = timestamp;
+ }
+
+ profile->Delete();
+}
+
static const char* cpu_profiler_test_source2 = "function loop() {}\n"
"function delay() { loop(); }\n"
--
--
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/d/optout.