OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/tracked_objects.h" | 5 #include "base/tracked_objects.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 // that we only record after parsing the command line flag --enable-tracking. | 26 // that we only record after parsing the command line flag --enable-tracking. |
27 // Note that the flag may force either state, so this really controls only the | 27 // Note that the flag may force either state, so this really controls only the |
28 // period of time up until that flag is parsed. If there is no flag seen, then | 28 // period of time up until that flag is parsed. If there is no flag seen, then |
29 // this state may prevail for much or all of the process lifetime. | 29 // this state may prevail for much or all of the process lifetime. |
30 static const ThreadData::Status kInitialStartupState = ThreadData::ACTIVE; | 30 static const ThreadData::Status kInitialStartupState = ThreadData::ACTIVE; |
31 } // anonymous namespace. | 31 } // anonymous namespace. |
32 | 32 |
33 //------------------------------------------------------------------------------ | 33 //------------------------------------------------------------------------------ |
34 // DeathData tallies durations when a death takes place. | 34 // DeathData tallies durations when a death takes place. |
35 | 35 |
36 void DeathData::RecordDeath(const Duration& queue_duration, | 36 void DeathData::RecordDeath(DurationInt queue_duration, |
37 const Duration& run_duration) { | 37 DurationInt run_duration) { |
38 ++count_; | 38 ++count_; |
39 queue_time_.AddDuration(queue_duration); | 39 queue_time_.AddDuration(queue_duration); |
40 run_time_.AddDuration(run_duration); | 40 run_time_.AddDuration(run_duration); |
41 } | 41 } |
42 | 42 |
43 int DeathData::AverageMsRunDuration() const { | 43 DurationInt DeathData::AverageMsRunDuration() const { |
44 return run_time_.AverageMsDuration(count_); | 44 return run_time_.AverageMsDuration(count_); |
45 } | 45 } |
46 | 46 |
47 int DeathData::AverageMsQueueDuration() const { | 47 DurationInt DeathData::AverageMsQueueDuration() const { |
48 return queue_time_.AverageMsDuration(count_); | 48 return queue_time_.AverageMsDuration(count_); |
49 } | 49 } |
50 | 50 |
51 void DeathData::AddDeathData(const DeathData& other) { | 51 void DeathData::AddDeathData(const DeathData& other) { |
52 count_ += other.count_; | 52 count_ += other.count_; |
53 queue_time_.AddData(other.queue_time_); | 53 queue_time_.AddData(other.queue_time_); |
54 run_time_.AddData(other.run_time_); | 54 run_time_.AddData(other.run_time_); |
55 } | 55 } |
56 | 56 |
57 void DeathData::WriteHTML(std::string* output) const { | 57 void DeathData::WriteHTML(std::string* output) const { |
58 if (!count_) | 58 if (!count_) |
59 return; | 59 return; |
60 base::StringAppendF(output, "%s:%d, ", | 60 base::StringAppendF(output, "%s:%d, ", |
61 (count_ == 1) ? "Life" : "Lives", count_); | 61 (count_ == 1) ? "Life" : "Lives", count_); |
62 output->append("Run:"); | 62 output->append("Run:"); |
63 run_time_.WriteHTML(count_, output); | 63 run_time_.WriteHTML(count_, output); |
64 | 64 |
65 output->append("Queue:"); | 65 output->append("Queue:"); |
66 queue_time_.WriteHTML(count_, output); | 66 queue_time_.WriteHTML(count_, output); |
67 } | 67 } |
68 | 68 |
69 base::DictionaryValue* DeathData::ToValue() const { | 69 base::DictionaryValue* DeathData::ToValue() const { |
70 base::DictionaryValue* dictionary = new base::DictionaryValue; | 70 base::DictionaryValue* dictionary = new base::DictionaryValue; |
71 dictionary->Set("count", base::Value::CreateIntegerValue(count_)); | 71 dictionary->Set("count", base::Value::CreateIntegerValue(count_)); |
72 dictionary->Set("run_ms", | 72 dictionary->Set("run_ms", |
73 base::Value::CreateIntegerValue(run_time_.duration().InMilliseconds())); | 73 base::Value::CreateIntegerValue(run_time_.duration())); |
74 dictionary->Set("queue_ms", | 74 dictionary->Set("queue_ms", |
75 base::Value::CreateIntegerValue(queue_time_.duration().InMilliseconds())); | 75 base::Value::CreateIntegerValue(queue_time_.duration())); |
76 dictionary->Set("run_ms_max", | 76 dictionary->Set("run_ms_max", |
77 base::Value::CreateIntegerValue(run_time_.max().InMilliseconds())); | 77 base::Value::CreateIntegerValue(run_time_.max())); |
78 dictionary->Set("queue_ms_max", | 78 dictionary->Set("queue_ms_max", |
79 base::Value::CreateIntegerValue(queue_time_.max().InMilliseconds())); | 79 base::Value::CreateIntegerValue(queue_time_.max())); |
80 return dictionary; | 80 return dictionary; |
81 } | 81 } |
82 | 82 |
83 void DeathData::Clear() { | 83 void DeathData::Clear() { |
84 count_ = 0; | 84 count_ = 0; |
85 run_time_.Clear(); | 85 run_time_.Clear(); |
86 queue_time_.Clear(); | 86 queue_time_.Clear(); |
87 } | 87 } |
88 | 88 |
89 //------------------------------------------------------------------------------ | 89 //------------------------------------------------------------------------------ |
90 | 90 |
91 void DeathData::Data::WriteHTML(int count, std::string* output) const { | 91 void DeathData::Data::WriteHTML(int count, std::string* output) const { |
92 // Be careful to leave static_casts intact, as the type returned by | 92 // Be careful to leave static_casts intact, as the type returned by |
93 // InMilliseconds() may not always be an int, even if it can generally fit | 93 // InMilliseconds() may not always be an int, even if it can generally fit |
94 // into an int. | 94 // into an int. |
95 base::StringAppendF(output, "%dms", | 95 base::StringAppendF(output, "%dms", |
96 static_cast<int>(duration_.InMilliseconds())); | 96 static_cast<int>(duration_)); |
97 if (count == 1) { | 97 if (count == 1) { |
98 output->append(" "); | 98 output->append(" "); |
99 return; | 99 return; |
100 } | 100 } |
101 base::StringAppendF(output, "(%dms/life,max:%dms) ", | 101 base::StringAppendF(output, "(%dms/life,max:%dms) ", |
102 AverageMsDuration(count), | 102 static_cast<int>(AverageMsDuration(count)), |
103 static_cast<int>(max_.InMilliseconds())); | 103 static_cast<int>(max_)); |
104 } | 104 } |
105 | 105 |
106 void DeathData::Data::AddData(const Data& other) { | 106 void DeathData::Data::AddData(const Data& other) { |
107 duration_ += other.duration_; | 107 duration_ += other.duration_; |
108 if (max_ > other.max_) | 108 if (max_ > other.max_) |
109 return; | 109 return; |
110 max_ = other.max_; | 110 max_ = other.max_; |
111 } | 111 } |
112 | 112 |
113 void DeathData::Data::AddDuration(const Duration& duration) { | 113 void DeathData::Data::AddDuration(DurationInt duration) { |
114 duration_ += duration; | 114 duration_ += duration; |
115 if (max_ > duration) | 115 if (max_ > duration) |
116 return; | 116 return; |
117 max_ = duration; | 117 max_ = duration; |
118 } | 118 } |
119 | 119 |
120 int DeathData::Data::AverageMsDuration(int count) const { | 120 DurationInt DeathData::Data::AverageMsDuration(int count) const { |
121 if (duration_ == Duration() || !count) | 121 if (duration_ == 0 || !count) |
122 return 0; | 122 return 0; |
123 return static_cast<int>(duration_.InMilliseconds() + count / 2) / count; | 123 return (duration_ + count / 2) / count; |
124 } | 124 } |
125 | 125 |
126 void DeathData::Data::Clear() { | 126 void DeathData::Data::Clear() { |
127 duration_ = Duration(); | 127 duration_ = 0; |
128 max_ = Duration(); | 128 max_ = 0; |
129 } | 129 } |
130 //------------------------------------------------------------------------------ | 130 //------------------------------------------------------------------------------ |
131 BirthOnThread::BirthOnThread(const Location& location, | 131 BirthOnThread::BirthOnThread(const Location& location, |
132 const ThreadData& current) | 132 const ThreadData& current) |
133 : location_(location), | 133 : location_(location), |
134 birth_thread_(¤t) {} | 134 birth_thread_(¤t) {} |
135 | 135 |
136 //------------------------------------------------------------------------------ | 136 //------------------------------------------------------------------------------ |
137 Births::Births(const Location& location, const ThreadData& current) | 137 Births::Births(const Location& location, const ThreadData& current) |
138 : BirthOnThread(location, current), | 138 : BirthOnThread(location, current), |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 | 394 |
395 Births* tracker = new Births(location, *this); | 395 Births* tracker = new Births(location, *this); |
396 // Lock since the map may get relocated now, and other threads sometimes | 396 // Lock since the map may get relocated now, and other threads sometimes |
397 // snapshot it (but they lock before copying it). | 397 // snapshot it (but they lock before copying it). |
398 base::AutoLock lock(lock_); | 398 base::AutoLock lock(lock_); |
399 birth_map_[location] = tracker; | 399 birth_map_[location] = tracker; |
400 return tracker; | 400 return tracker; |
401 } | 401 } |
402 | 402 |
403 void ThreadData::TallyADeath(const Births& birth, | 403 void ThreadData::TallyADeath(const Births& birth, |
404 const Duration& queue_duration, | 404 DurationInt queue_duration, |
405 const Duration& run_duration) { | 405 DurationInt run_duration) { |
406 DeathMap::iterator it = death_map_.find(&birth); | 406 DeathMap::iterator it = death_map_.find(&birth); |
407 DeathData* death_data; | 407 DeathData* death_data; |
408 if (it != death_map_.end()) { | 408 if (it != death_map_.end()) { |
409 death_data = &it->second; | 409 death_data = &it->second; |
410 } else { | 410 } else { |
411 base::AutoLock lock(lock_); // Lock since the map may get relocated now. | 411 base::AutoLock lock(lock_); // Lock since the map may get relocated now. |
412 death_data = &death_map_[&birth]; | 412 death_data = &death_map_[&birth]; |
413 } // Release lock ASAP. | 413 } // Release lock ASAP. |
414 death_data->RecordDeath(queue_duration, run_duration); | 414 death_data->RecordDeath(queue_duration, run_duration); |
415 } | 415 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 // have for non-delayed tasks, and we consistently call it queueing delay. | 453 // have for non-delayed tasks, and we consistently call it queueing delay. |
454 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() | 454 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() |
455 ? tracked_objects::TrackedTime(completed_task.time_posted) | 455 ? tracked_objects::TrackedTime(completed_task.time_posted) |
456 : tracked_objects::TrackedTime(completed_task.delayed_run_time); | 456 : tracked_objects::TrackedTime(completed_task.delayed_run_time); |
457 | 457 |
458 // Watch out for a race where status_ is changing, and hence one or both | 458 // Watch out for a race where status_ is changing, and hence one or both |
459 // of start_of_run or end_of_run is zero. IN that case, we didn't bother to | 459 // of start_of_run or end_of_run is zero. IN that case, we didn't bother to |
460 // get a time value since we "weren't tracking" and we were trying to be | 460 // get a time value since we "weren't tracking" and we were trying to be |
461 // efficient by not calling for a genuine time value. For simplicity, we'll | 461 // efficient by not calling for a genuine time value. For simplicity, we'll |
462 // use a default zero duration when we can't calculate a true value. | 462 // use a default zero duration when we can't calculate a true value. |
463 Duration queue_duration; | 463 DurationInt queue_duration = 0; |
464 Duration run_duration; | 464 DurationInt run_duration = 0; |
465 if (!start_of_run.is_null()) { | 465 if (!start_of_run.is_null()) { |
466 queue_duration = start_of_run - effective_post_time; | 466 queue_duration = (start_of_run - effective_post_time).InMilliseconds(); |
467 if (!end_of_run.is_null()) | 467 if (!end_of_run.is_null()) |
468 run_duration = end_of_run - start_of_run; | 468 run_duration = (end_of_run - start_of_run).InMilliseconds(); |
469 } | 469 } |
470 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 470 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
471 } | 471 } |
472 | 472 |
473 // static | 473 // static |
474 void ThreadData::TallyRunOnWorkerThreadIfTracking( | 474 void ThreadData::TallyRunOnWorkerThreadIfTracking( |
475 const Births* birth, | 475 const Births* birth, |
476 const TrackedTime& time_posted, | 476 const TrackedTime& time_posted, |
477 const TrackedTime& start_of_run, | 477 const TrackedTime& start_of_run, |
478 const TrackedTime& end_of_run) { | 478 const TrackedTime& end_of_run) { |
(...skipping 12 matching lines...) Expand all Loading... |
491 // (since we'll use locks on TallyBirth and TallyDeath). The good news is | 491 // (since we'll use locks on TallyBirth and TallyDeath). The good news is |
492 // that the locks on TallyDeath will be *after* the worker thread has run, and | 492 // that the locks on TallyDeath will be *after* the worker thread has run, and |
493 // hence nothing will be waiting for the completion (... besides some other | 493 // hence nothing will be waiting for the completion (... besides some other |
494 // thread that might like to run). Also, the worker threads tasks are | 494 // thread that might like to run). Also, the worker threads tasks are |
495 // generally longer, and hence the cost of the lock may perchance be amortized | 495 // generally longer, and hence the cost of the lock may perchance be amortized |
496 // over the long task's lifetime. | 496 // over the long task's lifetime. |
497 ThreadData* current_thread_data = Get(); | 497 ThreadData* current_thread_data = Get(); |
498 if (!current_thread_data) | 498 if (!current_thread_data) |
499 return; | 499 return; |
500 | 500 |
501 Duration queue_duration; | 501 DurationInt queue_duration = 0; |
502 Duration run_duration; | 502 DurationInt run_duration = 0; |
503 if (!start_of_run.is_null()) { | 503 if (!start_of_run.is_null()) { |
504 queue_duration = start_of_run - time_posted; | 504 queue_duration = (start_of_run - time_posted).InMilliseconds(); |
505 if (!end_of_run.is_null()) | 505 if (!end_of_run.is_null()) |
506 run_duration = end_of_run - start_of_run; | 506 run_duration = (end_of_run - start_of_run).InMilliseconds(); |
507 } | 507 } |
508 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 508 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
509 } | 509 } |
510 | 510 |
511 // static | 511 // static |
512 void ThreadData::TallyRunInAScopedRegionIfTracking( | 512 void ThreadData::TallyRunInAScopedRegionIfTracking( |
513 const Births* birth, | 513 const Births* birth, |
514 const TrackedTime& start_of_run, | 514 const TrackedTime& start_of_run, |
515 const TrackedTime& end_of_run) { | 515 const TrackedTime& end_of_run) { |
516 if (!kTrackAllTaskObjects) | 516 if (!kTrackAllTaskObjects) |
517 return; // Not compiled in. | 517 return; // Not compiled in. |
518 | 518 |
519 // Even if we have been DEACTIVATED, we will process any pending births so | 519 // Even if we have been DEACTIVATED, we will process any pending births so |
520 // that our data structures (which counted the outstanding births) remain | 520 // that our data structures (which counted the outstanding births) remain |
521 // consistent. | 521 // consistent. |
522 if (!birth) | 522 if (!birth) |
523 return; | 523 return; |
524 | 524 |
525 ThreadData* current_thread_data = Get(); | 525 ThreadData* current_thread_data = Get(); |
526 if (!current_thread_data) | 526 if (!current_thread_data) |
527 return; | 527 return; |
528 | 528 |
529 Duration queue_duration = Duration(); | 529 DurationInt queue_duration = 0; |
530 Duration run_duration = end_of_run - start_of_run; | 530 DurationInt run_duration = (end_of_run - start_of_run).InMilliseconds(); |
531 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 531 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
532 } | 532 } |
533 | 533 |
534 | 534 |
535 | 535 |
536 // static | 536 // static |
537 ThreadData* ThreadData::first() { | 537 ThreadData* ThreadData::first() { |
538 base::AutoLock lock(*list_lock_); | 538 base::AutoLock lock(*list_lock_); |
539 return all_thread_data_list_head_; | 539 return all_thread_data_list_head_; |
540 } | 540 } |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1247 (combined_selectors_ & BIRTH_THREAD) ? "*" : | 1247 (combined_selectors_ & BIRTH_THREAD) ? "*" : |
1248 sample.birth().birth_thread()->thread_name().c_str(), | 1248 sample.birth().birth_thread()->thread_name().c_str(), |
1249 (combined_selectors_ & DEATH_THREAD) ? "*" : | 1249 (combined_selectors_ & DEATH_THREAD) ? "*" : |
1250 sample.DeathThreadName().c_str()); | 1250 sample.DeathThreadName().c_str()); |
1251 sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE), | 1251 sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE), |
1252 !(combined_selectors_ & BIRTH_FUNCTION), | 1252 !(combined_selectors_ & BIRTH_FUNCTION), |
1253 output); | 1253 output); |
1254 } | 1254 } |
1255 | 1255 |
1256 } // namespace tracked_objects | 1256 } // namespace tracked_objects |
OLD | NEW |