| OLD | NEW |
| 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 "base/tracked_objects.h" | 5 #include "base/tracked_objects.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 } | 59 } |
| 60 | 60 |
| 61 // TODO(jar): I need to see if this macro to optimize branching is worth using. | 61 // TODO(jar): I need to see if this macro to optimize branching is worth using. |
| 62 // | 62 // |
| 63 // This macro has no branching, so it is surely fast, and is equivalent to: | 63 // This macro has no branching, so it is surely fast, and is equivalent to: |
| 64 // if (assign_it) | 64 // if (assign_it) |
| 65 // target = source; | 65 // target = source; |
| 66 // We use a macro rather than a template to force this to inline. | 66 // We use a macro rather than a template to force this to inline. |
| 67 // Related code for calculating max is discussed on the web. | 67 // Related code for calculating max is discussed on the web. |
| 68 #define CONDITIONAL_ASSIGN(assign_it, target, source) \ | 68 #define CONDITIONAL_ASSIGN(assign_it, target, source) \ |
| 69 ((target) ^= ((target) ^ (source)) & -static_cast<DurationInt>(assign_it)) | 69 ((target) ^= ((target) ^ (source)) & -static_cast<int32>(assign_it)) |
| 70 | 70 |
| 71 void DeathData::RecordDeath(const DurationInt queue_duration, | 71 void DeathData::RecordDeath(const int32 queue_duration, |
| 72 const DurationInt run_duration, | 72 const int32 run_duration, |
| 73 int32 random_number) { | 73 int32 random_number) { |
| 74 ++count_; | 74 ++count_; |
| 75 queue_duration_sum_ += queue_duration; | 75 queue_duration_sum_ += queue_duration; |
| 76 run_duration_sum_ += run_duration; | 76 run_duration_sum_ += run_duration; |
| 77 | 77 |
| 78 if (queue_duration_max_ < queue_duration) | 78 if (queue_duration_max_ < queue_duration) |
| 79 queue_duration_max_ = queue_duration; | 79 queue_duration_max_ = queue_duration; |
| 80 if (run_duration_max_ < run_duration) | 80 if (run_duration_max_ < run_duration) |
| 81 run_duration_max_ = run_duration; | 81 run_duration_max_ = run_duration; |
| 82 | 82 |
| 83 // Take a uniformly distributed sample over all durations ever supplied. | 83 // Take a uniformly distributed sample over all durations ever supplied. |
| 84 // The probability that we (instead) use this new sample is 1/count_. This | 84 // The probability that we (instead) use this new sample is 1/count_. This |
| 85 // results in a completely uniform selection of the sample. | 85 // results in a completely uniform selection of the sample. |
| 86 // We ignore the fact that we correlated our selection of a sample of run | 86 // We ignore the fact that we correlated our selection of a sample of run |
| 87 // and queue times. | 87 // and queue times. |
| 88 if (0 == (random_number % count_)) { | 88 if (0 == (random_number % count_)) { |
| 89 queue_duration_sample_ = queue_duration; | 89 queue_duration_sample_ = queue_duration; |
| 90 run_duration_sample_ = run_duration; | 90 run_duration_sample_ = run_duration; |
| 91 } | 91 } |
| 92 } | 92 } |
| 93 | 93 |
| 94 int DeathData::count() const { return count_; } | 94 int DeathData::count() const { return count_; } |
| 95 | 95 |
| 96 DurationInt DeathData::run_duration_sum() const { return run_duration_sum_; } | 96 int32 DeathData::run_duration_sum() const { return run_duration_sum_; } |
| 97 | 97 |
| 98 DurationInt DeathData::run_duration_max() const { return run_duration_max_; } | 98 int32 DeathData::run_duration_max() const { return run_duration_max_; } |
| 99 | 99 |
| 100 DurationInt DeathData::run_duration_sample() const { | 100 int32 DeathData::run_duration_sample() const { |
| 101 return run_duration_sample_; | 101 return run_duration_sample_; |
| 102 } | 102 } |
| 103 | 103 |
| 104 DurationInt DeathData::queue_duration_sum() const { | 104 int32 DeathData::queue_duration_sum() const { |
| 105 return queue_duration_sum_; | 105 return queue_duration_sum_; |
| 106 } | 106 } |
| 107 | 107 |
| 108 DurationInt DeathData::queue_duration_max() const { | 108 int32 DeathData::queue_duration_max() const { |
| 109 return queue_duration_max_; | 109 return queue_duration_max_; |
| 110 } | 110 } |
| 111 | 111 |
| 112 DurationInt DeathData::queue_duration_sample() const { | 112 int32 DeathData::queue_duration_sample() const { |
| 113 return queue_duration_sample_; | 113 return queue_duration_sample_; |
| 114 } | 114 } |
| 115 | 115 |
| 116 | 116 |
| 117 base::DictionaryValue* DeathData::ToValue() const { | 117 base::DictionaryValue* DeathData::ToValue() const { |
| 118 base::DictionaryValue* dictionary = new base::DictionaryValue; | 118 base::DictionaryValue* dictionary = new base::DictionaryValue; |
| 119 dictionary->Set("count", base::Value::CreateIntegerValue(count_)); | 119 dictionary->Set("count", base::Value::CreateIntegerValue(count_)); |
| 120 dictionary->Set("run_ms", | 120 dictionary->Set("run_ms", |
| 121 base::Value::CreateIntegerValue(run_duration_sum())); | 121 base::Value::CreateIntegerValue(run_duration_sum())); |
| 122 dictionary->Set("run_ms_max", | 122 dictionary->Set("run_ms_max", |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 // snapshot it (but they lock before copying it). | 367 // snapshot it (but they lock before copying it). |
| 368 base::AutoLock lock(map_lock_); | 368 base::AutoLock lock(map_lock_); |
| 369 parent_child_set_.insert(pair); | 369 parent_child_set_.insert(pair); |
| 370 } | 370 } |
| 371 } | 371 } |
| 372 | 372 |
| 373 return child; | 373 return child; |
| 374 } | 374 } |
| 375 | 375 |
| 376 void ThreadData::TallyADeath(const Births& birth, | 376 void ThreadData::TallyADeath(const Births& birth, |
| 377 DurationInt queue_duration, | 377 int32 queue_duration, |
| 378 DurationInt run_duration) { | 378 int32 run_duration) { |
| 379 // Stir in some randomness, plus add constant in case durations are zero. | 379 // Stir in some randomness, plus add constant in case durations are zero. |
| 380 const DurationInt kSomePrimeNumber = 2147483647; | 380 const int32 kSomePrimeNumber = 2147483647; |
| 381 random_number_ += queue_duration + run_duration + kSomePrimeNumber; | 381 random_number_ += queue_duration + run_duration + kSomePrimeNumber; |
| 382 // An address is going to have some randomness to it as well ;-). | 382 // An address is going to have some randomness to it as well ;-). |
| 383 random_number_ ^= static_cast<int32>(&birth - reinterpret_cast<Births*>(0)); | 383 random_number_ ^= static_cast<int32>(&birth - reinterpret_cast<Births*>(0)); |
| 384 | 384 |
| 385 // We don't have queue durations without OS timer. OS timer is automatically | 385 // We don't have queue durations without OS timer. OS timer is automatically |
| 386 // used for task-post-timing, so the use of an alternate timer implies all | 386 // used for task-post-timing, so the use of an alternate timer implies all |
| 387 // queue times are invalid. | 387 // queue times are invalid. |
| 388 if (kAllowAlternateTimeSourceHandling && now_function_) | 388 if (kAllowAlternateTimeSourceHandling && now_function_) |
| 389 queue_duration = 0; | 389 queue_duration = 0; |
| 390 | 390 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 // have for non-delayed tasks, and we consistently call it queueing delay. | 445 // have for non-delayed tasks, and we consistently call it queueing delay. |
| 446 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() | 446 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() |
| 447 ? tracked_objects::TrackedTime(completed_task.time_posted) | 447 ? tracked_objects::TrackedTime(completed_task.time_posted) |
| 448 : tracked_objects::TrackedTime(completed_task.delayed_run_time); | 448 : tracked_objects::TrackedTime(completed_task.delayed_run_time); |
| 449 | 449 |
| 450 // Watch out for a race where status_ is changing, and hence one or both | 450 // Watch out for a race where status_ is changing, and hence one or both |
| 451 // of start_of_run or end_of_run is zero. In that case, we didn't bother to | 451 // of start_of_run or end_of_run is zero. In that case, we didn't bother to |
| 452 // get a time value since we "weren't tracking" and we were trying to be | 452 // get a time value since we "weren't tracking" and we were trying to be |
| 453 // efficient by not calling for a genuine time value. For simplicity, we'll | 453 // efficient by not calling for a genuine time value. For simplicity, we'll |
| 454 // use a default zero duration when we can't calculate a true value. | 454 // use a default zero duration when we can't calculate a true value. |
| 455 DurationInt queue_duration = 0; | 455 int32 queue_duration = 0; |
| 456 DurationInt run_duration = 0; | 456 int32 run_duration = 0; |
| 457 if (!start_of_run.is_null()) { | 457 if (!start_of_run.is_null()) { |
| 458 queue_duration = (start_of_run - effective_post_time).InMilliseconds(); | 458 queue_duration = (start_of_run - effective_post_time).InMilliseconds(); |
| 459 if (!end_of_run.is_null()) | 459 if (!end_of_run.is_null()) |
| 460 run_duration = (end_of_run - start_of_run).InMilliseconds(); | 460 run_duration = (end_of_run - start_of_run).InMilliseconds(); |
| 461 } | 461 } |
| 462 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 462 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
| 463 } | 463 } |
| 464 | 464 |
| 465 // static | 465 // static |
| 466 void ThreadData::TallyRunOnWorkerThreadIfTracking( | 466 void ThreadData::TallyRunOnWorkerThreadIfTracking( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 483 // (since we'll use locks on TallyBirth and TallyDeath). The good news is | 483 // (since we'll use locks on TallyBirth and TallyDeath). The good news is |
| 484 // that the locks on TallyDeath will be *after* the worker thread has run, and | 484 // that the locks on TallyDeath will be *after* the worker thread has run, and |
| 485 // hence nothing will be waiting for the completion (... besides some other | 485 // hence nothing will be waiting for the completion (... besides some other |
| 486 // thread that might like to run). Also, the worker threads tasks are | 486 // thread that might like to run). Also, the worker threads tasks are |
| 487 // generally longer, and hence the cost of the lock may perchance be amortized | 487 // generally longer, and hence the cost of the lock may perchance be amortized |
| 488 // over the long task's lifetime. | 488 // over the long task's lifetime. |
| 489 ThreadData* current_thread_data = Get(); | 489 ThreadData* current_thread_data = Get(); |
| 490 if (!current_thread_data) | 490 if (!current_thread_data) |
| 491 return; | 491 return; |
| 492 | 492 |
| 493 DurationInt queue_duration = 0; | 493 int32 queue_duration = 0; |
| 494 DurationInt run_duration = 0; | 494 int32 run_duration = 0; |
| 495 if (!start_of_run.is_null()) { | 495 if (!start_of_run.is_null()) { |
| 496 queue_duration = (start_of_run - time_posted).InMilliseconds(); | 496 queue_duration = (start_of_run - time_posted).InMilliseconds(); |
| 497 if (!end_of_run.is_null()) | 497 if (!end_of_run.is_null()) |
| 498 run_duration = (end_of_run - start_of_run).InMilliseconds(); | 498 run_duration = (end_of_run - start_of_run).InMilliseconds(); |
| 499 } | 499 } |
| 500 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 500 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
| 501 } | 501 } |
| 502 | 502 |
| 503 // static | 503 // static |
| 504 void ThreadData::TallyRunInAScopedRegionIfTracking( | 504 void ThreadData::TallyRunInAScopedRegionIfTracking( |
| 505 const Births* birth, | 505 const Births* birth, |
| 506 const TrackedTime& start_of_run, | 506 const TrackedTime& start_of_run, |
| 507 const TrackedTime& end_of_run) { | 507 const TrackedTime& end_of_run) { |
| 508 if (!kTrackAllTaskObjects) | 508 if (!kTrackAllTaskObjects) |
| 509 return; // Not compiled in. | 509 return; // Not compiled in. |
| 510 | 510 |
| 511 // Even if we have been DEACTIVATED, we will process any pending births so | 511 // Even if we have been DEACTIVATED, we will process any pending births so |
| 512 // that our data structures (which counted the outstanding births) remain | 512 // that our data structures (which counted the outstanding births) remain |
| 513 // consistent. | 513 // consistent. |
| 514 if (!birth) | 514 if (!birth) |
| 515 return; | 515 return; |
| 516 | 516 |
| 517 ThreadData* current_thread_data = Get(); | 517 ThreadData* current_thread_data = Get(); |
| 518 if (!current_thread_data) | 518 if (!current_thread_data) |
| 519 return; | 519 return; |
| 520 | 520 |
| 521 DurationInt queue_duration = 0; | 521 int32 queue_duration = 0; |
| 522 DurationInt run_duration = 0; | 522 int32 run_duration = 0; |
| 523 if (!start_of_run.is_null() && !end_of_run.is_null()) | 523 if (!start_of_run.is_null() && !end_of_run.is_null()) |
| 524 run_duration = (end_of_run - start_of_run).InMilliseconds(); | 524 run_duration = (end_of_run - start_of_run).InMilliseconds(); |
| 525 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 525 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
| 526 } | 526 } |
| 527 | 527 |
| 528 const std::string ThreadData::thread_name() const { return thread_name_; } | 528 const std::string ThreadData::thread_name() const { return thread_name_; } |
| 529 | 529 |
| 530 // This may be called from another thread. | 530 // This may be called from another thread. |
| 531 void ThreadData::SnapshotMaps(bool reset_max, | 531 void ThreadData::SnapshotMaps(bool reset_max, |
| 532 BirthMap* birth_map, | 532 BirthMap* birth_map, |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 ++it) { | 882 ++it) { |
| 883 base::DictionaryValue* parent_child = new base::DictionaryValue; | 883 base::DictionaryValue* parent_child = new base::DictionaryValue; |
| 884 it->first->ToValue("parent", parent_child); | 884 it->first->ToValue("parent", parent_child); |
| 885 it->second->ToValue("child", parent_child); | 885 it->second->ToValue("child", parent_child); |
| 886 descendants->Append(parent_child); | 886 descendants->Append(parent_child); |
| 887 } | 887 } |
| 888 dictionary->Set("descendants", descendants); | 888 dictionary->Set("descendants", descendants); |
| 889 } | 889 } |
| 890 | 890 |
| 891 } // namespace tracked_objects | 891 } // namespace tracked_objects |
| OLD | NEW |