diff options
author | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-15 23:05:01 +0000 |
---|---|---|
committer | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-15 23:05:01 +0000 |
commit | 90895d0f3265926221f00b3571332066a0bcb375 (patch) | |
tree | ee36e96f7bc1bfd52d0370cfc9324bee7ac1d631 /base/tracked_objects.cc | |
parent | a8c119da0066b18c472559dd80e58e9895d5ee06 (diff) | |
download | chromium_src-90895d0f3265926221f00b3571332066a0bcb375.zip chromium_src-90895d0f3265926221f00b3571332066a0bcb375.tar.gz chromium_src-90895d0f3265926221f00b3571332066a0bcb375.tar.bz2 |
Support use of third party time function for about:profiler
This uses TCMalloc to provide a time function, allowing
us to see how much memory was allocated on a single thread
during the running of a task. The alternate time function
is put in place only when a specific environment variable
is detected during TCMalloc startup.
This change currently is activated only in Windows/Linux,
as it is based on changes TCMalloc (not used on Mac).
We also create an infrastructure for using any alternate
timer, to replace the "wall clock time," on a per-thread
basis, in the about:profiler infrastructure. That interface
may be used on other platforms, including scenarios where
we have a per-thread-CPU-time function to replace the
wall-clock timer. In all cases, when this alternate timer
is activated, we lose the ability to calculated queueing
time. Queueing time is based on a time snapshot taken on
a second thread, and hence is not comparable to the
alternate timer (when the alternate timer is engaged).
r=rtenneti
BUG=103321
Review URL: https://chromiumcodereview.appspot.com/9212025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122180 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/tracked_objects.cc')
-rw-r--r-- | base/tracked_objects.cc | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index 87af8dc..c837b9a 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc @@ -8,6 +8,7 @@ #include "base/format_macros.h" #include "base/message_loop.h" +#include "base/profiler/alternate_timer.h" #include "base/stringprintf.h" #include "base/third_party/valgrind/memcheck.h" #include "base/threading/thread_restrictions.h" @@ -35,6 +36,14 @@ const bool kTrackParentChildLinks = false; const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_CHILDREN_ACTIVE; +// Control whether an alternate time source (Now() function) is supported by +// the ThreadData class. This compile time flag should be set to true if we +// want other modules (such as a memory allocator, or a thread-specific CPU time +// clock) to be able to provide a thread-specific Now() function. Without this +// compile-time flag, the code will only support the wall-clock time. This flag +// can be flipped to efficiently disable this path (if there is a performance +// problem with its presence). +static const bool kAllowAlternateTimeSourceHandling = true; } // namespace //------------------------------------------------------------------------------ @@ -176,6 +185,9 @@ void Births::Clear() { birth_count_ = 0; } // optimize layout so that we benefit from locality of reference during accesses // to them. +// static +NowFunction* ThreadData::now_function_ = NULL; + // A TLS slot which points to the ThreadData instance for the current thread. We // do a fake initialization here (zeroing out data), and then the real in-place // construction happens when we call tls_index_.Initialize(). @@ -370,6 +382,12 @@ void ThreadData::TallyADeath(const Births& birth, // An address is going to have some randomness to it as well ;-). random_number_ ^= static_cast<int32>(&birth - reinterpret_cast<Births*>(0)); + // We don't have queue durations without OS timer. OS timer is automatically + // used for task-post-timing, so the use of an alternate timer implies all + // queue times are invalid. + if (kAllowAlternateTimeSourceHandling && now_function_) + queue_duration = 0; + DeathMap::iterator it = death_map_.find(&birth); DeathData* death_data; if (it != death_map_.end()) { @@ -579,6 +597,24 @@ void ThreadData::Reset() { it->second->Clear(); } +static void OptionallyInitializeAlternateTimer() { + char* alternate_selector = getenv(kAlternateProfilerTime); + if (!alternate_selector) + return; + switch (*alternate_selector) { + case '0': // This is the default value, and uses the wall clock time. + break; + case '1': { + // Use the TCMalloc allocations-on-thread as a pseudo-time. + ThreadData::SetAlternateTimeSource(GetAlternateTimeSource()); + break; + } + default: + NOTREACHED(); + break; + } +} + bool ThreadData::Initialize() { if (!kTrackAllTaskObjects) return false; // Not compiled in. @@ -594,6 +630,13 @@ bool ThreadData::Initialize() { if (status_ >= DEACTIVATED) return true; // Someone raced in here and beat us. + // Put an alternate timer in place if the environment calls for it, such as + // for tracking TCMalloc allocations. This insertion is idempotent, so we + // don't mind if there is a race, and we'd prefer not to be in a lock while + // doing this work. + if (kAllowAlternateTimeSourceHandling) + OptionallyInitializeAlternateTimer(); + // Perform the "real" TLS initialization now, and leave it intact through // process termination. if (!tls_index_.initialized()) { // Testing may have initialized this. @@ -666,7 +709,16 @@ TrackedTime ThreadData::NowForEndOfRun() { } // static +void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { + DCHECK(now_function); + if (kAllowAlternateTimeSourceHandling) + now_function_ = now_function; +} + +// static TrackedTime ThreadData::Now() { + if (kAllowAlternateTimeSourceHandling && now_function_) + return TrackedTime::FromMilliseconds((*now_function_)()); if (kTrackAllTaskObjects && TrackingStatus()) return TrackedTime::Now(); return TrackedTime(); // Super fast when disabled, or not compiled. |