summaryrefslogtreecommitdiffstats
path: root/base/tracked_objects.cc
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-15 23:05:01 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-15 23:05:01 +0000
commit90895d0f3265926221f00b3571332066a0bcb375 (patch)
treeee36e96f7bc1bfd52d0370cfc9324bee7ac1d631 /base/tracked_objects.cc
parenta8c119da0066b18c472559dd80e58e9895d5ee06 (diff)
downloadchromium_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.cc52
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.