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

Side by Side Diff: content/browser/tracing/trace_controller_impl.cc

Issue 23556003: Implement about:tracing UI for the sampling profiler (Chromium part) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/browser/tracing/trace_controller_impl.h" 5 #include "content/browser/tracing/trace_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 46
47 } // namespace 47 } // namespace
48 48
49 TraceController* TraceController::GetInstance() { 49 TraceController* TraceController::GetInstance() {
50 return TraceControllerImpl::GetInstance(); 50 return TraceControllerImpl::GetInstance();
51 } 51 }
52 52
53 TraceControllerImpl::TraceControllerImpl() : 53 TraceControllerImpl::TraceControllerImpl() :
54 subscriber_(NULL), 54 subscriber_(NULL),
55 pending_end_ack_count_(0), 55 pending_end_ack_count_(0),
56 pending_show_continuous_sampling_ack_count_(0),
56 pending_bpf_ack_count_(0), 57 pending_bpf_ack_count_(0),
57 maximum_bpf_(0.0f), 58 maximum_bpf_(0.0f),
58 is_tracing_(false), 59 is_tracing_(false),
60 is_continuous_sampling_tracing_(false),
59 is_get_category_groups_(false), 61 is_get_category_groups_(false),
60 category_filter_( 62 category_filter_(
61 base::debug::CategoryFilter::kDefaultCategoryFilterString) { 63 base::debug::CategoryFilter::kDefaultCategoryFilterString) {
62 TraceLog::GetInstance()->SetNotificationCallback( 64 TraceLog::GetInstance()->SetNotificationCallback(
63 base::Bind(&TraceControllerImpl::OnTraceNotification, 65 base::Bind(&TraceControllerImpl::OnTraceNotification,
64 base::Unretained(this))); 66 base::Unretained(this)));
65 } 67 }
66 68
67 TraceControllerImpl::~TraceControllerImpl() { 69 TraceControllerImpl::~TraceControllerImpl() {
68 // No need to SetNotificationCallback(nil) on the TraceLog since this is a 70 // No need to SetNotificationCallback(nil) on the TraceLog since this is a
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
132 134
133 if (!can_begin_tracing(subscriber)) 135 if (!can_begin_tracing(subscriber))
134 return false; 136 return false;
135 137
136 // Enable tracing 138 // Enable tracing
137 TraceLog::GetInstance()->SetEnabled( 139 TraceLog::GetInstance()->SetEnabled(
138 base::debug::CategoryFilter(category_patterns), options); 140 base::debug::CategoryFilter(category_patterns), options);
139 141
140 OnTracingBegan(subscriber); 142 OnTracingBegan(subscriber);
141
142 return true; 143 return true;
143 } 144 }
144 145
145 bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) { 146 bool TraceControllerImpl::EndTracingAsync(TraceSubscriber* subscriber) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147 148
148 if (!can_end_tracing() || subscriber != subscriber_) 149 if (!can_end_tracing(subscriber))
149 return false; 150 return false;
150 151
151 // There could be a case where there are no child processes and filters_ 152 // There could be a case where there are no child processes and filters_
152 // is empty. In that case we can immediately tell the subscriber that tracing 153 // is empty. In that case we can immediately tell the subscriber that tracing
153 // has ended. To avoid recursive calls back to the subscriber, we will just 154 // has ended. To avoid recursive calls back to the subscriber, we will just
154 // use the existing asynchronous OnEndTracingAck code. 155 // use the existing asynchronous OnEndTracingAck code.
155 // Count myself (local trace) in pending_end_ack_count_, acked below. 156 // Count myself (local trace) in pending_end_ack_count_, acked below.
156 pending_end_ack_count_ = filters_.size() + 1; 157 pending_end_ack_count_ = filters_.size() + 1;
157 158
158 // Handle special case of zero child processes. 159 // Handle special case of zero child processes.
159 if (pending_end_ack_count_ == 1) { 160 if (pending_end_ack_count_ == 1) {
160 // Ack asynchronously now, because we don't have any children to wait for. 161 // Ack asynchronously now, because we don't have any children to wait for.
161 std::vector<std::string> category_groups; 162 std::vector<std::string> category_groups;
162 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); 163 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
163 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 164 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
164 base::Bind(&TraceControllerImpl::OnEndTracingAck, 165 base::Bind(&TraceControllerImpl::OnEndTracingAck,
165 base::Unretained(this), category_groups)); 166 base::Unretained(this), category_groups));
166 } 167 }
167 168
168 // Notify all child processes. 169 // Notify all child processes.
169 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { 170 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
170 it->get()->SendEndTracing(); 171 it->get()->SendEndTracing();
171 } 172 }
172 173
173 return true; 174 return true;
174 } 175 }
175 176
177 bool TraceControllerImpl::BeginContinuousSamplingTracing(
178 TraceSubscriber* subscriber) {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
180
181 if (!can_begin_continuous_sampling_tracing(subscriber))
182 return false;
183
184 is_continuous_sampling_tracing_ = true;
185 continuous_sampling_subscriber_ = subscriber;
186
187 // Notify all child processes.
188 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
189 it->get()->SendBeginContinuousSamplingTracing();
190 }
191 return true;
192 }
193
194 bool TraceControllerImpl::EndContinuousSamplingTracing(
195 TraceSubscriber* subscriber) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
197
198 if (!can_end_continuous_sampling_tracing(subscriber))
199 return false;
200
201 is_continuous_sampling_tracing_ = false;
202 continuous_sampling_subscriber_ = NULL;
203
204 // Notify all child processes.
205 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
206 it->get()->SendEndContinuousSamplingTracing();
207 }
208 return true;
209 }
210
211 bool TraceControllerImpl::ShowContinuousSamplingTracingAsync(
212 TraceSubscriber* subscriber) {
213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
214
215 if (!can_end_continuous_sampling_tracing(subscriber))
216 return false;
217
218 // There could be a case where there are no child processes and filters_
219 // is empty. In that case we can immediately tell the subscriber that tracing
220 // has ended. To avoid recursive calls back to the subscriber, we will just
221 // use the existing asynchronous OnShowContinuousSamplingTracingAck code.
222 // Count myself (local trace) in pending_show_continuous_sampling_ack_count_,
223 // acked below.
224 pending_show_continuous_sampling_ack_count_ = filters_.size() + 1;
225
226 // Handle special case of zero child processes.
227 if (pending_show_continuous_sampling_ack_count_ == 1) {
228 // Ack asynchronously now, because we don't have any children to wait for.
229 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
230 base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck,
231 base::Unretained(this)));
232 }
233
234 // Notify all child processes.
235 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
236 it->get()->SendShowContinuousSamplingTracing();
237 }
238 return true;
239 }
240
176 bool TraceControllerImpl::GetTraceBufferPercentFullAsync( 241 bool TraceControllerImpl::GetTraceBufferPercentFullAsync(
177 TraceSubscriber* subscriber) { 242 TraceSubscriber* subscriber) {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179 244
180 if (!can_get_buffer_percent_full() || subscriber != subscriber_) 245 if (!can_get_buffer_percent_full() || subscriber != subscriber_)
181 return false; 246 return false;
182 247
183 maximum_bpf_ = 0.0f; 248 maximum_bpf_ = 0.0f;
184 pending_bpf_ack_count_ = filters_.size() + 1; 249 pending_bpf_ack_count_ = filters_.size() + 1;
185 250
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 296
232 return true; 297 return true;
233 } 298 }
234 299
235 void TraceControllerImpl::CancelSubscriber(TraceSubscriber* subscriber) { 300 void TraceControllerImpl::CancelSubscriber(TraceSubscriber* subscriber) {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 302
238 if (subscriber == subscriber_) { 303 if (subscriber == subscriber_) {
239 subscriber_ = NULL; 304 subscriber_ = NULL;
240 // End tracing if necessary. 305 // End tracing if necessary.
241 if (is_tracing_ && pending_end_ack_count_ == 0) 306 if (is_tracing_enabled())
242 EndTracingAsync(NULL); 307 EndTracingAsync(NULL);
243 } 308 }
244 } 309 }
245 310
246 void TraceControllerImpl::AddFilter(TraceMessageFilter* filter) { 311 void TraceControllerImpl::AddFilter(TraceMessageFilter* filter) {
247 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 312 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
248 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 313 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
249 base::Bind(&TraceControllerImpl::AddFilter, base::Unretained(this), 314 base::Bind(&TraceControllerImpl::AddFilter, base::Unretained(this),
250 make_scoped_refptr(filter))); 315 make_scoped_refptr(filter)));
251 return; 316 return;
252 } 317 }
253 318
254 filters_.insert(filter); 319 filters_.insert(filter);
255 if (is_tracing_enabled()) { 320 if (is_tracing_enabled()) {
256 std::string cf_str = category_filter_.ToString(); 321 std::string cf_str = category_filter_.ToString();
257 filter->SendBeginTracing(cf_str, trace_options_); 322 filter->SendBeginTracing(cf_str, trace_options_);
258 if (!watch_category_.empty()) 323 if (!watch_category_.empty())
259 filter->SendSetWatchEvent(watch_category_, watch_name_); 324 filter->SendSetWatchEvent(watch_category_, watch_name_);
260 } 325 }
326 if (is_continuous_sampling_tracing_enabled()) {
327 filter->SendBeginContinuousSamplingTracing();
328 }
261 } 329 }
262 330
263 void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) { 331 void TraceControllerImpl::RemoveFilter(TraceMessageFilter* filter) {
264 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 332 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
265 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 333 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
266 base::Bind(&TraceControllerImpl::RemoveFilter, base::Unretained(this), 334 base::Bind(&TraceControllerImpl::RemoveFilter, base::Unretained(this),
267 make_scoped_refptr(filter))); 335 make_scoped_refptr(filter)));
268 return; 336 return;
269 } 337 }
270 338
271 filters_.erase(filter); 339 filters_.erase(filter);
272 } 340 }
273 341
274 void TraceControllerImpl::OnTracingBegan(TraceSubscriber* subscriber) { 342 void TraceControllerImpl::OnTracingBegan(TraceSubscriber* subscriber) {
275 is_tracing_ = true; 343 is_tracing_ = true;
276
277 subscriber_ = subscriber; 344 subscriber_ = subscriber;
278 345
279 category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter(); 346 category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter();
280 trace_options_ = TraceLog::GetInstance()->trace_options(); 347 trace_options_ = TraceLog::GetInstance()->trace_options();
281 348
282 // Notify all child processes. 349 // Notify all child processes.
283 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { 350 for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
284 it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_); 351 it->get()->SendBeginTracing(category_filter_.ToString(), trace_options_);
285 } 352 }
286 } 353 }
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 base::Bind(&TraceControllerImpl::OnTraceDataCollected, 416 base::Bind(&TraceControllerImpl::OnTraceDataCollected,
350 base::Unretained(this), events_str_ptr)); 417 base::Unretained(this), events_str_ptr));
351 return; 418 return;
352 } 419 }
353 420
354 // Drop trace events if we are just getting categories. 421 // Drop trace events if we are just getting categories.
355 if (subscriber_ && !is_get_category_groups_) 422 if (subscriber_ && !is_get_category_groups_)
356 subscriber_->OnTraceDataCollected(events_str_ptr); 423 subscriber_->OnTraceDataCollected(events_str_ptr);
357 } 424 }
358 425
426 void TraceControllerImpl::OnShowContinuousSamplingTracingAck() {
427 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
428 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
429 base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck,
430 base::Unretained(this)));
431 return;
432 }
433
434 if (pending_show_continuous_sampling_ack_count_ == 0)
435 return;
436
437 if (--pending_show_continuous_sampling_ack_count_ == 0) {
438 // During this call, our OnContinuousSamplingTraceDataCollected will be
439 // called with the last of the local trace data. Since we are on the UI
440 // thread, the call to OnContinuousSamplingTraceDataCollected will be
441 // synchronous, so we can immediately call
442 // OnShowContinuousSamplingTracingComplete below.
443 TraceLog::GetInstance()->FlushContinuousSamplingTracing(
444 base::Bind(&TraceControllerImpl::OnContinuousSamplingTraceDataCollected,
445 base::Unretained(this)));
446
447 if (continuous_sampling_subscriber_)
448 continuous_sampling_subscriber_->
449 OnShowContinuousSamplingTracingComplete();
450 }
451
452 if (pending_show_continuous_sampling_ack_count_ == 1) {
453 // The last ack represents local trace, so we need to ack it now. Note that
454 // this code only executes if there were child processes.
455 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
456 base::Bind(&TraceControllerImpl::OnShowContinuousSamplingTracingAck,
457 base::Unretained(this)));
458 }
459 }
460
461 void TraceControllerImpl::OnContinuousSamplingTraceDataCollected(
462 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
463 // OnContinuousSamplingTraceDataCollected may be called from
464 // any browser thread, either by the local event trace system or
465 // from child processes via TraceMessageFilter.
466 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
467 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
468 base::Bind(&TraceControllerImpl::
469 OnContinuousSamplingTraceDataCollected,
470 base::Unretained(this), events_str_ptr));
471 return;
472 }
473
474 // Drop trace events if we are just getting categories.
475 if (continuous_sampling_subscriber_)
476 continuous_sampling_subscriber_->
477 OnContinuousSamplingTraceDataCollected(events_str_ptr);
478 }
479
359 void TraceControllerImpl::OnTraceNotification(int notification) { 480 void TraceControllerImpl::OnTraceNotification(int notification) {
360 // OnTraceNotification may be called from any browser thread, either by the 481 // OnTraceNotification may be called from any browser thread, either by the
361 // local event trace system or from child processes via TraceMessageFilter. 482 // local event trace system or from child processes via TraceMessageFilter.
362 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 483 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
363 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 484 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
364 base::Bind(&TraceControllerImpl::OnTraceNotification, 485 base::Bind(&TraceControllerImpl::OnTraceNotification,
365 base::Unretained(this), notification)); 486 base::Unretained(this), notification));
366 return; 487 return;
367 } 488 }
368 489
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 // The last ack represents local trace, so we need to ack it now. Note that 521 // The last ack represents local trace, so we need to ack it now. Note that
401 // this code only executes if there were child processes. 522 // this code only executes if there were child processes.
402 float bpf = TraceLog::GetInstance()->GetBufferPercentFull(); 523 float bpf = TraceLog::GetInstance()->GetBufferPercentFull();
403 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 524 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
404 base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply, 525 base::Bind(&TraceControllerImpl::OnTraceBufferPercentFullReply,
405 base::Unretained(this), bpf)); 526 base::Unretained(this), bpf));
406 } 527 }
407 } 528 }
408 529
409 } // namespace content 530 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/tracing/trace_controller_impl.h ('k') | content/browser/tracing/trace_message_filter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698