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

Side by Side Diff: content/renderer/devtools/v8_sampling_profiler.cc

Issue 792903003: V8 Sampling Profiler: Collect V8 JitCodeEvents in tracing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix the test under Debug mode. Created 5 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/devtools/v8_sampling_profiler.h" 5 #include "content/renderer/devtools/v8_sampling_profiler.h"
6 6
7 #include "base/format_macros.h"
8 #include "base/strings/string_util.h"
7 #include "base/synchronization/cancellation_flag.h" 9 #include "base/synchronization/cancellation_flag.h"
8 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
9 #include "base/trace_event/trace_event.h" 11 #include "base/trace_event/trace_event.h"
12 #include "base/trace_event/trace_event_argument.h"
13 #include "content/renderer/render_thread_impl.h"
14 #include "v8/include/v8.h"
15
16 using base::trace_event::TraceLog;
17 using base::trace_event::TracedValue;
18 using v8::Isolate;
10 19
11 namespace content { 20 namespace content {
12 21
22 namespace {
23
24 std::string PtrToString(const void* value) {
25 char buffer[20];
26 base::snprintf(buffer, sizeof(buffer), "0x%" PRIx64,
27 static_cast<uint64>(reinterpret_cast<intptr_t>(value)));
28 return buffer;
29 }
30
31 } // namespace
32
33 // The class implements a sampler responsible for sampling a single thread.
34 class Sampler {
35 public:
36 explicit Sampler(Isolate* isolate) : isolate_(isolate) { DCHECK(isolate_); }
37
38 static scoped_ptr<Sampler> CreateForCurrentThread();
39
40 // These methods are called from the sampling thread.
41 void Start();
42 void Stop();
43 void Sample();
44
45 private:
46 static void InstallJitCodeEventHandler(Isolate* isolate, void* data);
47 static void HandleJitCodeEvent(const v8::JitCodeEvent* event);
48 static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
49 JitCodeEventToTraceFormat(const v8::JitCodeEvent* event);
50
51 Isolate* isolate_;
52 };
53
54 // static
55 scoped_ptr<Sampler> Sampler::CreateForCurrentThread() {
56 return scoped_ptr<Sampler>(new Sampler(Isolate::GetCurrent()));
57 }
58
59 void Sampler::Start() {
60 v8::JitCodeEventHandler handler = &HandleJitCodeEvent;
61 isolate_->RequestInterrupt(&InstallJitCodeEventHandler,
62 reinterpret_cast<void*>(handler));
63 }
64
65 void Sampler::Stop() {
66 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, nullptr);
67 }
68
69 void Sampler::Sample() {
70 }
71
72 // static
73 void Sampler::InstallJitCodeEventHandler(Isolate* isolate, void* data) {
74 // Called on the sampled V8 thread.
75 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
76 "Sampler::InstallJitCodeEventHandler");
77 v8::JitCodeEventHandler handler =
78 reinterpret_cast<v8::JitCodeEventHandler>(data);
79 isolate->SetJitCodeEventHandler(
80 v8::JitCodeEventOptions::kJitCodeEventEnumExisting, handler);
81 }
82
83 // static
84 void Sampler::HandleJitCodeEvent(const v8::JitCodeEvent* event) {
85 // Called on the sampled V8 thread.
86 switch (event->type) {
87 case v8::JitCodeEvent::CODE_ADDED:
88 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
89 "JitCodeAdded", TRACE_EVENT_SCOPE_THREAD, "data",
90 JitCodeEventToTraceFormat(event));
91 break;
92
93 case v8::JitCodeEvent::CODE_MOVED:
94 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
95 "JitCodeMoved", TRACE_EVENT_SCOPE_THREAD, "data",
96 JitCodeEventToTraceFormat(event));
97 break;
98
99 case v8::JitCodeEvent::CODE_REMOVED:
100 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
101 "JitCodeRemoved", TRACE_EVENT_SCOPE_THREAD, "data",
102 JitCodeEventToTraceFormat(event));
103 break;
104
105 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO:
106 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING:
107 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING:
108 break;
109 }
110 }
111
112 // static
113 scoped_refptr<base::trace_event::ConvertableToTraceFormat>
114 Sampler::JitCodeEventToTraceFormat(const v8::JitCodeEvent* event) {
115 // Called on the sampled thread.
116 switch (event->type) {
117 case v8::JitCodeEvent::CODE_ADDED: {
118 scoped_refptr<TracedValue> data(new TracedValue());
119 data->SetString("code_start", PtrToString(event->code_start));
120 data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
121 data->SetString("name", std::string(event->name.str, event->name.len));
122 return data;
123 }
124
125 case v8::JitCodeEvent::CODE_MOVED: {
126 scoped_refptr<TracedValue> data(new TracedValue());
127 data->SetString("code_start", PtrToString(event->code_start));
128 data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
129 data->SetString("new_code_start", PtrToString(event->new_code_start));
130 return data;
131 }
132
133 case v8::JitCodeEvent::CODE_REMOVED: {
134 scoped_refptr<TracedValue> data(new TracedValue());
135 data->SetString("code_start", PtrToString(event->code_start));
136 data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
137 return data;
138 }
139
140 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO:
141 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING:
142 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING:
143 return nullptr;
144 }
145 return nullptr;
146 }
147
13 class V8SamplingThread : public base::PlatformThread::Delegate { 148 class V8SamplingThread : public base::PlatformThread::Delegate {
14 public: 149 public:
15 explicit V8SamplingThread(base::WaitableEvent* event); 150 V8SamplingThread(Sampler*, base::WaitableEvent*);
16 151
17 // Implementation of PlatformThread::Delegate: 152 // Implementation of PlatformThread::Delegate:
18 void ThreadMain() override; 153 void ThreadMain() override;
19 154
20 void Start(); 155 void Start();
21 void Stop(); 156 void Stop();
22 157
23 private: 158 private:
159 void Sample();
160 void InstallSamplers();
161 void RemoveSamplers();
162 void StartSamplers();
163 void StopSamplers();
164 static void HandleJitCodeEvent(const v8::JitCodeEvent* event);
165
166 Sampler* render_thread_sampler_;
24 base::CancellationFlag cancellation_flag_; 167 base::CancellationFlag cancellation_flag_;
25 base::WaitableEvent* waitable_event_for_testing_; 168 base::WaitableEvent* waitable_event_for_testing_;
26 base::PlatformThreadHandle sampling_thread_handle_; 169 base::PlatformThreadHandle sampling_thread_handle_;
170 std::vector<Sampler*> samplers_;
27 171
28 DISALLOW_COPY_AND_ASSIGN(V8SamplingThread); 172 DISALLOW_COPY_AND_ASSIGN(V8SamplingThread);
29 }; 173 };
30 174
31 V8SamplingThread::V8SamplingThread(base::WaitableEvent* event) 175 V8SamplingThread::V8SamplingThread(Sampler* render_thread_sampler,
32 : waitable_event_for_testing_(event) { 176 base::WaitableEvent* event)
177 : render_thread_sampler_(render_thread_sampler),
178 waitable_event_for_testing_(event) {
33 } 179 }
34 180
35 void V8SamplingThread::ThreadMain() { 181 void V8SamplingThread::ThreadMain() {
36 base::PlatformThread::SetName("V8 Sampling Profiler Thread"); 182 base::PlatformThread::SetName("V8SamplingProfilerThread");
183 InstallSamplers();
184 StartSamplers();
37 const int kSamplingFrequencyMicroseconds = 1000; 185 const int kSamplingFrequencyMicroseconds = 1000;
38 while (!cancellation_flag_.IsSet()) { 186 while (!cancellation_flag_.IsSet()) {
187 Sample();
39 if (waitable_event_for_testing_) { 188 if (waitable_event_for_testing_) {
40 waitable_event_for_testing_->Signal(); 189 waitable_event_for_testing_->Signal();
41 } 190 }
42 base::PlatformThread::Sleep( 191 base::PlatformThread::Sleep(
43 base::TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds)); 192 base::TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds));
44 } 193 }
194 StopSamplers();
195 RemoveSamplers();
196 }
197
198 void V8SamplingThread::Sample() {
199 for (Sampler* sampler : samplers_) {
200 sampler->Sample();
201 }
202 }
203
204 void V8SamplingThread::InstallSamplers() {
205 // Note that the list does not own samplers.
206 samplers_.push_back(render_thread_sampler_);
207 // TODO: add worker samplers.
208 }
209
210 void V8SamplingThread::RemoveSamplers() {
211 samplers_.clear();
212 }
213
214 void V8SamplingThread::StartSamplers() {
215 for (Sampler* sampler : samplers_) {
216 sampler->Start();
217 }
218 }
219
220 void V8SamplingThread::StopSamplers() {
221 for (Sampler* sampler : samplers_) {
222 sampler->Stop();
223 }
45 } 224 }
46 225
47 void V8SamplingThread::Start() { 226 void V8SamplingThread::Start() {
48 if (!base::PlatformThread::Create(0, this, &sampling_thread_handle_)) { 227 if (!base::PlatformThread::Create(0, this, &sampling_thread_handle_)) {
49 DCHECK(false) << "failed to create thread"; 228 DCHECK(false) << "failed to create thread";
50 } 229 }
51 } 230 }
52 231
53 void V8SamplingThread::Stop() { 232 void V8SamplingThread::Stop() {
54 cancellation_flag_.Set(); 233 cancellation_flag_.Set();
55 base::PlatformThread::Join(sampling_thread_handle_); 234 base::PlatformThread::Join(sampling_thread_handle_);
56 } 235 }
57 236
58 V8SamplingProfiler::V8SamplingProfiler() : sampling_thread_(nullptr) { 237 V8SamplingProfiler::V8SamplingProfiler(bool underTest)
59 // Force the "v8_cpu_profile" category to show up in the trace viewer. 238 : sampling_thread_(nullptr),
60 base::trace_event::TraceLog::GetCategoryGroupEnabled( 239 render_thread_sampler_(Sampler::CreateForCurrentThread()) {
61 TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile")); 240 DCHECK(underTest || RenderThreadImpl::current());
62 base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); 241 // Force the "v8.cpu_profile" category to show up in the trace viewer.
242 TraceLog::GetCategoryGroupEnabled(
243 TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"));
244 TraceLog::GetInstance()->AddEnabledStateObserver(this);
63 } 245 }
64 246
65 V8SamplingProfiler::~V8SamplingProfiler() { 247 V8SamplingProfiler::~V8SamplingProfiler() {
66 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); 248 TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
67 DCHECK(!sampling_thread_.get()); 249 DCHECK(!sampling_thread_.get());
68 } 250 }
69 251
70 void V8SamplingProfiler::OnTraceLogEnabled() { 252 void V8SamplingProfiler::OnTraceLogEnabled() {
71 bool enabled; 253 bool enabled;
72 TRACE_EVENT_CATEGORY_GROUP_ENABLED( 254 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
73 TRACE_DISABLED_BY_DEFAULT("v8_cpu_profile"), &enabled); 255 TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"), &enabled);
74 if (!enabled) 256 if (!enabled)
75 return; 257 return;
258
259 // Do not enable sampling profiler in continuous mode, as losing
260 // Jit code events may not be afforded.
261 base::trace_event::TraceRecordMode record_mode =
262 TraceLog::GetInstance()->GetCurrentTraceOptions().record_mode;
263 if (record_mode == base::trace_event::TraceRecordMode::RECORD_CONTINUOUSLY)
264 return;
265
76 DCHECK(!sampling_thread_.get()); 266 DCHECK(!sampling_thread_.get());
77 sampling_thread_.reset( 267 sampling_thread_.reset(new V8SamplingThread(
78 new V8SamplingThread(waitable_event_for_testing_.get())); 268 render_thread_sampler_.get(), waitable_event_for_testing_.get()));
79 sampling_thread_->Start(); 269 sampling_thread_->Start();
80 } 270 }
81 271
82 void V8SamplingProfiler::OnTraceLogDisabled() { 272 void V8SamplingProfiler::OnTraceLogDisabled() {
83 if (!sampling_thread_.get()) 273 if (!sampling_thread_.get())
84 return; 274 return;
85 sampling_thread_->Stop(); 275 sampling_thread_->Stop();
86 sampling_thread_.reset(); 276 sampling_thread_.reset();
87 } 277 }
88 278
89 void V8SamplingProfiler::EnableSamplingEventForTesting() { 279 void V8SamplingProfiler::EnableSamplingEventForTesting() {
90 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); 280 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false));
91 } 281 }
92 282
93 void V8SamplingProfiler::WaitSamplingEventForTesting() { 283 void V8SamplingProfiler::WaitSamplingEventForTesting() {
94 waitable_event_for_testing_->Wait(); 284 waitable_event_for_testing_->Wait();
95 } 285 }
96 286
97 } // namespace blink 287 } // namespace blink
OLDNEW
« no previous file with comments | « content/renderer/devtools/v8_sampling_profiler.h ('k') | content/renderer/devtools/v8_sampling_profiler_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698