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

Side by Side Diff: base/tracked_objects.cc

Issue 9212025: Support use of third party time function to profiler (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « base/tracked_objects.h ('k') | third_party/tcmalloc/chromium/src/tcmalloc.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "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"
11 #include "base/profiler/alternate_timer.h"
11 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
12 #include "base/third_party/valgrind/memcheck.h" 13 #include "base/third_party/valgrind/memcheck.h"
13 #include "base/threading/thread_restrictions.h" 14 #include "base/threading/thread_restrictions.h"
14 #include "build/build_config.h" 15 #include "build/build_config.h"
15 #include "base/port.h" 16 #include "base/port.h"
16 17
17 using base::TimeDelta; 18 using base::TimeDelta;
18 19
19 namespace tracked_objects { 20 namespace tracked_objects {
20 21
21 namespace { 22 namespace {
22 23
23 // Flag to compile out almost all of the task tracking code. 24 // Flag to compile out almost all of the task tracking code.
24 const bool kTrackAllTaskObjects = true; 25 const bool kTrackAllTaskObjects = true;
25 26
26 // Flag to compile out parent-child link recording. 27 // Flag to compile out parent-child link recording.
27 const bool kTrackParentChildLinks = false; 28 const bool kTrackParentChildLinks = false;
28 29
29 // When ThreadData is first initialized, should we start in an ACTIVE state to 30 // When ThreadData is first initialized, should we start in an ACTIVE state to
30 // record all of the startup-time tasks, or should we start up DEACTIVATED, so 31 // record all of the startup-time tasks, or should we start up DEACTIVATED, so
31 // that we only record after parsing the command line flag --enable-tracking. 32 // that we only record after parsing the command line flag --enable-tracking.
32 // Note that the flag may force either state, so this really controls only the 33 // Note that the flag may force either state, so this really controls only the
33 // period of time up until that flag is parsed. If there is no flag seen, then 34 // period of time up until that flag is parsed. If there is no flag seen, then
34 // this state may prevail for much or all of the process lifetime. 35 // this state may prevail for much or all of the process lifetime.
35 const ThreadData::Status kInitialStartupState = 36 const ThreadData::Status kInitialStartupState =
36 ThreadData::PROFILING_CHILDREN_ACTIVE; 37 ThreadData::PROFILING_CHILDREN_ACTIVE;
37 38
39 // Control whether an alternate time source (Now() function) is supported by
40 // the ThreadData class. This compile time flag should be set to true if we
41 // want other modules (such as a memory allocator, or a thread-specific CPU time
42 // clock) to be able to provide a thread-specific Now() function. Without this
43 // compile-time flag, the code will only support the wall-clock time. This flag
44 // can be flipped to efficiently disable this path (if there is a performance
45 // problem with its presence).
46 static const bool kAllowAlternateTimeSourceHandling = true;
38 } // namespace 47 } // namespace
39 48
40 //------------------------------------------------------------------------------ 49 //------------------------------------------------------------------------------
41 // DeathData tallies durations when a death takes place. 50 // DeathData tallies durations when a death takes place.
42 51
43 DeathData::DeathData() { 52 DeathData::DeathData() {
44 Clear(); 53 Clear();
45 } 54 }
46 55
47 DeathData::DeathData(int count) { 56 DeathData::DeathData(int count) {
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 void Births::Clear() { birth_count_ = 0; } 178 void Births::Clear() { birth_count_ = 0; }
170 179
171 //------------------------------------------------------------------------------ 180 //------------------------------------------------------------------------------
172 // ThreadData maintains the central data for all births and deaths on a single 181 // ThreadData maintains the central data for all births and deaths on a single
173 // thread. 182 // thread.
174 183
175 // TODO(jar): We should pull all these static vars together, into a struct, and 184 // TODO(jar): We should pull all these static vars together, into a struct, and
176 // optimize layout so that we benefit from locality of reference during accesses 185 // optimize layout so that we benefit from locality of reference during accesses
177 // to them. 186 // to them.
178 187
188 // static
189 NowFunction* ThreadData::now_function_ = NULL;
190
179 // A TLS slot which points to the ThreadData instance for the current thread. We 191 // A TLS slot which points to the ThreadData instance for the current thread. We
180 // do a fake initialization here (zeroing out data), and then the real in-place 192 // do a fake initialization here (zeroing out data), and then the real in-place
181 // construction happens when we call tls_index_.Initialize(). 193 // construction happens when we call tls_index_.Initialize().
182 // static 194 // static
183 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; 195 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER;
184 196
185 // static 197 // static
186 int ThreadData::worker_thread_data_creation_count_ = 0; 198 int ThreadData::worker_thread_data_creation_count_ = 0;
187 199
188 // static 200 // static
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 375
364 void ThreadData::TallyADeath(const Births& birth, 376 void ThreadData::TallyADeath(const Births& birth,
365 DurationInt queue_duration, 377 DurationInt queue_duration,
366 DurationInt run_duration) { 378 DurationInt run_duration) {
367 // 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.
368 const DurationInt kSomePrimeNumber = 2147483647; 380 const DurationInt kSomePrimeNumber = 2147483647;
369 random_number_ += queue_duration + run_duration + kSomePrimeNumber; 381 random_number_ += queue_duration + run_duration + kSomePrimeNumber;
370 // 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 ;-).
371 random_number_ ^= static_cast<int32>(&birth - reinterpret_cast<Births*>(0)); 383 random_number_ ^= static_cast<int32>(&birth - reinterpret_cast<Births*>(0));
372 384
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
387 // queue times are invalid.
388 if (kAllowAlternateTimeSourceHandling && now_function_)
389 queue_duration = 0;
390
373 DeathMap::iterator it = death_map_.find(&birth); 391 DeathMap::iterator it = death_map_.find(&birth);
374 DeathData* death_data; 392 DeathData* death_data;
375 if (it != death_map_.end()) { 393 if (it != death_map_.end()) {
376 death_data = &it->second; 394 death_data = &it->second;
377 } else { 395 } else {
378 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. 396 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now.
379 death_data = &death_map_[&birth]; 397 death_data = &death_map_[&birth];
380 } // Release lock ASAP. 398 } // Release lock ASAP.
381 death_data->RecordDeath(queue_duration, run_duration, random_number_); 399 death_data->RecordDeath(queue_duration, run_duration, random_number_);
382 400
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 void ThreadData::Reset() { 590 void ThreadData::Reset() {
573 base::AutoLock lock(map_lock_); 591 base::AutoLock lock(map_lock_);
574 for (DeathMap::iterator it = death_map_.begin(); 592 for (DeathMap::iterator it = death_map_.begin();
575 it != death_map_.end(); ++it) 593 it != death_map_.end(); ++it)
576 it->second.Clear(); 594 it->second.Clear();
577 for (BirthMap::iterator it = birth_map_.begin(); 595 for (BirthMap::iterator it = birth_map_.begin();
578 it != birth_map_.end(); ++it) 596 it != birth_map_.end(); ++it)
579 it->second->Clear(); 597 it->second->Clear();
580 } 598 }
581 599
600 static void OptionallyInitializeAlternateTimer() {
601 char* alternate_selector = getenv(kAlternateProfilerTime);
602 if (!alternate_selector)
603 return;
604 switch (*alternate_selector) {
605 case '0': // This is the default value, and uses the wall clock time.
606 break;
607 case '1': {
608 // Use the TCMalloc allocations-on-thread as a pseudo-time.
609 ThreadData::SetAlternateTimeSource(GetAlternateTimeSource());
610 break;
611 }
612 default:
613 NOTREACHED();
614 break;
615 }
616 }
617
582 bool ThreadData::Initialize() { 618 bool ThreadData::Initialize() {
583 if (!kTrackAllTaskObjects) 619 if (!kTrackAllTaskObjects)
584 return false; // Not compiled in. 620 return false; // Not compiled in.
585 if (status_ >= DEACTIVATED) 621 if (status_ >= DEACTIVATED)
586 return true; // Someone else did the initialization. 622 return true; // Someone else did the initialization.
587 // Due to racy lazy initialization in tests, we'll need to recheck status_ 623 // Due to racy lazy initialization in tests, we'll need to recheck status_
588 // after we acquire the lock. 624 // after we acquire the lock.
589 625
590 // Ensure that we don't double initialize tls. We are called when single 626 // Ensure that we don't double initialize tls. We are called when single
591 // threaded in the product, but some tests may be racy and lazy about our 627 // threaded in the product, but some tests may be racy and lazy about our
592 // initialization. 628 // initialization.
593 base::AutoLock lock(*list_lock_.Pointer()); 629 base::AutoLock lock(*list_lock_.Pointer());
594 if (status_ >= DEACTIVATED) 630 if (status_ >= DEACTIVATED)
595 return true; // Someone raced in here and beat us. 631 return true; // Someone raced in here and beat us.
596 632
633 // Put an alternate timer in place if the environment calls for it, such as
634 // for tracking TCMalloc allocations. This insertion is idempotent, so we
635 // don't mind if there is a race, and we'd prefer not to be in a lock while
636 // doing this work.
637 if (kAllowAlternateTimeSourceHandling)
638 OptionallyInitializeAlternateTimer();
639
597 // Perform the "real" TLS initialization now, and leave it intact through 640 // Perform the "real" TLS initialization now, and leave it intact through
598 // process termination. 641 // process termination.
599 if (!tls_index_.initialized()) { // Testing may have initialized this. 642 if (!tls_index_.initialized()) { // Testing may have initialized this.
600 DCHECK_EQ(status_, UNINITIALIZED); 643 DCHECK_EQ(status_, UNINITIALIZED);
601 tls_index_.Initialize(&ThreadData::OnThreadTermination); 644 tls_index_.Initialize(&ThreadData::OnThreadTermination);
602 if (!tls_index_.initialized()) 645 if (!tls_index_.initialized())
603 return false; 646 return false;
604 } else { 647 } else {
605 // TLS was initialzed for us earlier. 648 // TLS was initialzed for us earlier.
606 DCHECK_EQ(status_, DORMANT_DURING_TESTS); 649 DCHECK_EQ(status_, DORMANT_DURING_TESTS);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
659 } 702 }
660 return Now(); 703 return Now();
661 } 704 }
662 705
663 // static 706 // static
664 TrackedTime ThreadData::NowForEndOfRun() { 707 TrackedTime ThreadData::NowForEndOfRun() {
665 return Now(); 708 return Now();
666 } 709 }
667 710
668 // static 711 // static
712 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) {
713 DCHECK(now_function);
714 if (kAllowAlternateTimeSourceHandling)
715 now_function_ = now_function;
716 }
717
718 // static
669 TrackedTime ThreadData::Now() { 719 TrackedTime ThreadData::Now() {
720 if (kAllowAlternateTimeSourceHandling && now_function_)
721 return TrackedTime::FromMilliseconds((*now_function_)());
670 if (kTrackAllTaskObjects && TrackingStatus()) 722 if (kTrackAllTaskObjects && TrackingStatus())
671 return TrackedTime::Now(); 723 return TrackedTime::Now();
672 return TrackedTime(); // Super fast when disabled, or not compiled. 724 return TrackedTime(); // Super fast when disabled, or not compiled.
673 } 725 }
674 726
675 // static 727 // static
676 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) { 728 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) {
677 base::AutoLock lock(*list_lock_.Pointer()); 729 base::AutoLock lock(*list_lock_.Pointer());
678 if (worker_thread_data_creation_count_ == 0) 730 if (worker_thread_data_creation_count_ == 0)
679 return; // We haven't really run much, and couldn't have leaked. 731 return; // We haven't really run much, and couldn't have leaked.
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 ++it) { 882 ++it) {
831 base::DictionaryValue* parent_child = new base::DictionaryValue; 883 base::DictionaryValue* parent_child = new base::DictionaryValue;
832 it->first->ToValue("parent", parent_child); 884 it->first->ToValue("parent", parent_child);
833 it->second->ToValue("child", parent_child); 885 it->second->ToValue("child", parent_child);
834 descendants->Append(parent_child); 886 descendants->Append(parent_child);
835 } 887 }
836 dictionary->Set("descendants", descendants); 888 dictionary->Set("descendants", descendants);
837 } 889 }
838 890
839 } // namespace tracked_objects 891 } // namespace tracked_objects
OLDNEW
« no previous file with comments | « base/tracked_objects.h ('k') | third_party/tcmalloc/chromium/src/tcmalloc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698