diff options
-rw-r--r-- | base/base.gypi | 2 | ||||
-rw-r--r-- | base/location.h | 6 | ||||
-rw-r--r-- | base/message_loop.cc | 20 | ||||
-rw-r--r-- | base/message_loop.h | 16 | ||||
-rw-r--r-- | base/threading/thread.cc | 2 | ||||
-rw-r--r-- | base/threading/worker_pool_posix.cc | 19 | ||||
-rw-r--r-- | base/threading/worker_pool_posix.h | 6 | ||||
-rw-r--r-- | base/threading/worker_pool_win.cc | 24 | ||||
-rw-r--r-- | base/tracked_objects.cc | 308 | ||||
-rw-r--r-- | base/tracked_objects.h | 254 | ||||
-rw-r--r-- | base/tracked_objects_unittest.cc | 401 | ||||
-rw-r--r-- | base/tracking_info.cc | 23 | ||||
-rw-r--r-- | base/tracking_info.h | 41 | ||||
-rw-r--r-- | chrome/browser/browser_about_handler.cc | 12 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 7 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.h | 2 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 25 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 3 | ||||
-rw-r--r-- | content/browser/browser_main_loop.cc | 3 |
19 files changed, 393 insertions, 781 deletions
diff --git a/base/base.gypi b/base/base.gypi index dd99be3..8fa20dc 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -336,8 +336,6 @@ 'timer.h', 'tracked_objects.cc', 'tracked_objects.h', - 'tracking_info.cc', - 'tracking_info.h', 'tuple.h', 'utf_offset_string_conversions.cc', 'utf_offset_string_conversions.h', diff --git a/base/location.h b/base/location.h index 523bfaf..42b3a92 100644 --- a/base/location.h +++ b/base/location.h @@ -10,6 +10,12 @@ #include "base/base_export.h" #include "base/values.h" +#ifndef NDEBUG +#ifndef TRACK_ALL_TASK_OBJECTS +#define TRACK_ALL_TASK_OBJECTS +#endif // TRACK_ALL_TASK_OBJECTS +#endif // NDEBUG + namespace tracked_objects { // Location provides basic info where of an object was constructed, or was diff --git a/base/message_loop.cc b/base/message_loop.cc index c1d4abb..553efb1 100644 --- a/base/message_loop.cc +++ b/base/message_loop.cc @@ -486,16 +486,20 @@ void MessageLoop::RunTask(const PendingTask& pending_task) { HistogramEvent(kTaskRunEvent); - tracked_objects::TrackedTime start_time = tracked_objects::ThreadData::Now(); +#if defined(TRACK_ALL_TASK_OBJECTS) + TimeTicks start_of_run = tracked_objects::ThreadData::Now(); +#endif // defined(TRACK_ALL_TASK_OBJECTS) FOR_EACH_OBSERVER(TaskObserver, task_observers_, WillProcessTask(pending_task.time_posted)); pending_task.task.Run(); FOR_EACH_OBSERVER(TaskObserver, task_observers_, DidProcessTask(pending_task.time_posted)); - - tracked_objects::ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - start_time, tracked_objects::ThreadData::Now()); +#if defined(TRACK_ALL_TASK_OBJECTS) + tracked_objects::ThreadData::TallyADeathIfActive(pending_task.post_births, + pending_task.time_posted, pending_task.delayed_run_time, start_of_run, + tracked_objects::ThreadData::Now()); +#endif // defined(TRACK_ALL_TASK_OBJECTS) nestable_tasks_allowed_ = true; } @@ -775,11 +779,15 @@ MessageLoop::PendingTask::PendingTask( const tracked_objects::Location& posted_from, TimeTicks delayed_run_time, bool nestable) - : base::TrackingInfo(posted_from, delayed_run_time), - task(task), + : task(task), + time_posted(TimeTicks::Now()), + delayed_run_time(delayed_run_time), posted_from(posted_from), sequence_num(0), nestable(nestable) { +#if defined(TRACK_ALL_TASK_OBJECTS) + post_births = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); +#endif // defined(TRACK_ALL_TASK_OBJECTS) } MessageLoop::PendingTask::~PendingTask() { diff --git a/base/message_loop.h b/base/message_loop.h index d94dc2f..732de03 100644 --- a/base/message_loop.h +++ b/base/message_loop.h @@ -19,7 +19,6 @@ #include "base/observer_list.h" #include "base/synchronization/lock.h" #include "base/task.h" -#include "base/tracking_info.h" #include "base/time.h" #if defined(OS_WIN) @@ -45,9 +44,11 @@ namespace base { class Histogram; } +#if defined(TRACK_ALL_TASK_OBJECTS) namespace tracked_objects { class Births; } +#endif // defined(TRACK_ALL_TASK_OBJECTS) // A MessageLoop is used to process events for a particular thread. There is // at most one MessageLoop instance per thread. @@ -409,7 +410,7 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate { #endif // This structure is copied around by value. - struct PendingTask : public base::TrackingInfo { + struct PendingTask { PendingTask(const base::Closure& task, const tracked_objects::Location& posted_from, base::TimeTicks delayed_run_time, @@ -422,6 +423,17 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate { // The task to run. base::Closure task; +#if defined(TRACK_ALL_TASK_OBJECTS) + // Counter for location where the Closure was posted from. + tracked_objects::Births* post_births; +#endif // defined(TRACK_ALL_TASK_OBJECTS) + + // Time this PendingTask was posted. + base::TimeTicks time_posted; + + // The time when the task should be run. + base::TimeTicks delayed_run_time; + // The site this PendingTask was posted from. tracked_objects::Location posted_from; diff --git a/base/threading/thread.cc b/base/threading/thread.cc index d49f247..2a8d999 100644 --- a/base/threading/thread.cc +++ b/base/threading/thread.cc @@ -152,7 +152,9 @@ void Thread::ThreadMain() { ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. message_loop.set_thread_name(name_); message_loop_ = &message_loop; +#if defined(TRACK_ALL_TASK_OBJECTS) tracked_objects::ThreadData::InitializeThreadContext(name_); +#endif // TRACK_ALL_TASK_OBJECTS // Let the thread do extra initialization. // Let's do this before signaling we are started. diff --git a/base/threading/worker_pool_posix.cc b/base/threading/worker_pool_posix.cc index 917565d..41fa01a 100644 --- a/base/threading/worker_pool_posix.cc +++ b/base/threading/worker_pool_posix.cc @@ -88,14 +88,15 @@ void WorkerThread::ThreadMain() { "src_file", pending_task.posted_from.file_name(), "src_func", pending_task.posted_from.function_name()); - tracked_objects::TrackedTime start_time = - tracked_objects::ThreadData::Now(); - +#if defined(TRACK_ALL_TASK_OBJECTS) + TimeTicks start_of_run = tracked_objects::ThreadData::Now(); +#endif // defined(TRACK_ALL_TASK_OBJECTS) pending_task.task.Run(); - - tracked_objects::ThreadData::TallyRunOnWorkerThreadIfTracking( - pending_task.birth_tally, pending_task.time_posted, - start_time, tracked_objects::ThreadData::Now()); +#if defined(TRACK_ALL_TASK_OBJECTS) + tracked_objects::ThreadData::TallyADeathIfActive(pending_task.post_births, + pending_task.time_posted, TimeTicks(), start_of_run, + tracked_objects::ThreadData::Now()); +#endif // defined(TRACK_ALL_TASK_OBJECTS) } // The WorkerThread is non-joinable, so it deletes itself. @@ -121,8 +122,10 @@ PosixDynamicThreadPool::PendingTask::PendingTask( const base::Closure& task) : posted_from(posted_from), task(task) { - birth_tally = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); +#if defined(TRACK_ALL_TASK_OBJECTS) + post_births = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); time_posted = tracked_objects::ThreadData::Now(); +#endif // defined(TRACK_ALL_TASK_OBJECTS) } PosixDynamicThreadPool::PendingTask::~PendingTask() { diff --git a/base/threading/worker_pool_posix.h b/base/threading/worker_pool_posix.h index 2cc1150..c0a60cc 100644 --- a/base/threading/worker_pool_posix.h +++ b/base/threading/worker_pool_posix.h @@ -53,11 +53,13 @@ class BASE_EXPORT PosixDynamicThreadPool const base::Closure& task); ~PendingTask(); +#if defined(TRACK_ALL_TASK_OBJECTS) // Counter for location where the Closure was posted from. - tracked_objects::Births* birth_tally; + tracked_objects::Births* post_births; // Time the task was posted. - tracked_objects::TrackedTime time_posted; + TimeTicks time_posted; +#endif // defined(TRACK_ALL_TASK_OBJECTS) const tracked_objects::Location posted_from; diff --git a/base/threading/worker_pool_win.cc b/base/threading/worker_pool_win.cc index b73cabd..0cd3d96 100644 --- a/base/threading/worker_pool_win.cc +++ b/base/threading/worker_pool_win.cc @@ -20,15 +20,19 @@ struct PendingTask { const base::Closure& task) : posted_from(posted_from), task(task) { - birth_tally = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); +#if defined(TRACK_ALL_TASK_OBJECTS) + post_births = tracked_objects::ThreadData::TallyABirthIfActive(posted_from); time_posted = tracked_objects::ThreadData::Now(); +#endif // defined(TRACK_ALL_TASK_OBJECTS) } +#if defined(TRACK_ALL_TASK_OBJECTS) // Counter for location where the Closure was posted from. - tracked_objects::Births* birth_tally; + tracked_objects::Births* post_births; // Time the task was posted. - tracked_objects::TrackedTime time_posted; + TimeTicks time_posted; +#endif // defined(TRACK_ALL_TASK_OBJECTS) // The site this PendingTask was posted from. tracked_objects::Location posted_from; @@ -43,13 +47,15 @@ DWORD CALLBACK WorkItemCallback(void* param) { "src_file", pending_task->posted_from.file_name(), "src_func", pending_task->posted_from.function_name()); - tracked_objects::TrackedTime start_time = tracked_objects::ThreadData::Now(); - +#if defined(TRACK_ALL_TASK_OBJECTS) + TimeTicks start_of_run = tracked_objects::ThreadData::Now(); +#endif // defined(TRACK_ALL_TASK_OBJECTS) pending_task->task.Run(); - - tracked_objects::ThreadData::TallyRunOnWorkerThreadIfTracking( - pending_task->birth_tally, pending_task->time_posted, - start_time, tracked_objects::ThreadData::Now()); +#if defined(TRACK_ALL_TASK_OBJECTS) + tracked_objects::ThreadData::TallyADeathIfActive(pending_task->post_births, + pending_task->time_posted, TimeTicks::TimeTicks(), start_of_run, + tracked_objects::ThreadData::Now()); +#endif // defined(TRACK_ALL_TASK_OBJECTS) delete pending_task; return 0; diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index 470d157..dfb88eb 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc @@ -16,43 +16,52 @@ using base::TimeDelta; namespace tracked_objects { -namespace { -// Flag to compile out almost all of the task tracking code. + +#if defined(TRACK_ALL_TASK_OBJECTS) static const bool kTrackAllTaskObjects = true; +#else +static const bool kTrackAllTaskObjects = false; +#endif + +// Can we count on thread termination to call for thread cleanup? If not, then +// we can't risk putting references to ThreadData in TLS, as it will leak on +// worker thread termination. +static const bool kWorkerThreadCleanupSupported = true; -// When ThreadData is first initialized, should we start in an ACTIVE state to -// record all of the startup-time tasks, or should we start up DEACTIVATED, so -// that we only record after parsing the command line flag --enable-tracking. -// Note that the flag may force either state, so this really controls only the -// period of time up until that flag is parsed. If there is no flag seen, then -// this state may prevail for much or all of the process lifetime. -static const ThreadData::Status kInitialStartupState = ThreadData::ACTIVE; -} // anonymous namespace. +// 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(). +// static +base::ThreadLocalStorage::Slot ThreadData::tls_index_(base::LINKER_INITIALIZED); + +// A global state variable to prevent repeated initialization during tests. +// static +AutoTracking::State AutoTracking::state_ = AutoTracking::kNeverBeenRun; + +// A locked protected counter to assign sequence number to threads. +// static +int ThreadData::thread_number_counter_ = 0; //------------------------------------------------------------------------------ // Death data tallies durations when a death takes place. -void DeathData::RecordDeath(const Duration& queue_duration, - const Duration& run_duration) { +void DeathData::RecordDeath(const TimeDelta& queue_duration, + const TimeDelta& run_duration) { ++count_; queue_duration_ += queue_duration; run_duration_ += run_duration; } int DeathData::AverageMsRunDuration() const { - if (run_duration_ == Duration() || !count_) + if (run_duration_ == base::TimeDelta()) return 0; - // Add half of denominator to achieve rounding. - return static_cast<int>(run_duration_.InMilliseconds() + count_ / 2) / - count_; + return static_cast<int>(run_duration_.InMilliseconds() / count_); } int DeathData::AverageMsQueueDuration() const { - if (queue_duration_ == Duration() || !count_) + if (queue_duration_ == base::TimeDelta()) return 0; - // Add half of denominator to achieve rounding. - return (static_cast<int>(queue_duration_.InMilliseconds() + count_ / 2) / - count_); + return static_cast<int>(queue_duration_.InMilliseconds() / count_); } void DeathData::AddDeathData(const DeathData& other) { @@ -66,14 +75,11 @@ void DeathData::WriteHTML(std::string* output) const { return; base::StringAppendF(output, "%s:%d, ", (count_ == 1) ? "Life" : "Lives", count_); - // Be careful to leave static_casts intact, as the type returned by - // InMilliseconds() may not always be an int, even if it can generally fit - // into an int. - base::StringAppendF(output, "Run:%dms(%dms/life) ", - static_cast<int>(run_duration_.InMilliseconds()), + base::StringAppendF(output, "Run:%"PRId64"ms(%dms/life) ", + run_duration_.InMilliseconds(), AverageMsRunDuration()); - base::StringAppendF(output, "Queue:%dms(%dms/life) ", - static_cast<int>(queue_duration_.InMilliseconds()), + base::StringAppendF(output, "Queue:%"PRId64"ms(%dms/life) ", + queue_duration_.InMilliseconds(), AverageMsQueueDuration()); } @@ -89,8 +95,8 @@ base::DictionaryValue* DeathData::ToValue() const { void DeathData::Clear() { count_ = 0; - queue_duration_ = Duration(); - run_duration_ = Duration(); + queue_duration_ = TimeDelta(); + run_duration_ = TimeDelta(); } //------------------------------------------------------------------------------ @@ -107,20 +113,6 @@ Births::Births(const Location& location, const ThreadData& current) //------------------------------------------------------------------------------ // ThreadData maintains the central data for all births and deaths. -// TODO(jar): We should pull all these static vars together, into a struct, and -// optimize layout so that we benefit from locality of reference during accesses -// to them. - -// 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(). -// static -base::ThreadLocalStorage::Slot ThreadData::tls_index_(base::LINKER_INITIALIZED); - -// A lock-protected counter to assign sequence number to threads. -// static -int ThreadData::thread_number_counter_ = 0; - // static ThreadData* ThreadData::all_thread_data_list_head_ = NULL; @@ -128,7 +120,7 @@ ThreadData* ThreadData::all_thread_data_list_head_ = NULL; ThreadData::ThreadDataPool* ThreadData::unregistered_thread_data_pool_ = NULL; // static -base::Lock* ThreadData::list_lock_; +base::Lock ThreadData::list_lock_; // static ThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED; @@ -144,7 +136,7 @@ ThreadData::ThreadData(const std::string& suggested_name) ThreadData::ThreadData() : next_(NULL), is_a_worker_thread_(true) { int thread_number; { - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); thread_number = ++thread_number_counter_; } base::StringAppendF(&thread_name_, "WorkerThread-%d", thread_number); @@ -155,20 +147,17 @@ ThreadData::~ThreadData() {} void ThreadData::PushToHeadOfList() { DCHECK(!next_); - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); next_ = all_thread_data_list_head_; all_thread_data_list_head_ = this; } // static void ThreadData::InitializeThreadContext(const std::string& suggested_name) { - if (!Initialize()) // Always initialize if needed. - return; - ThreadData* current_thread_data = - reinterpret_cast<ThreadData*>(tls_index_.Get()); - if (current_thread_data) - return; // Browser tests instigate this. - current_thread_data = new ThreadData(suggested_name); + if (!tls_index_.initialized()) + return; // For unittests only. + DCHECK_EQ(tls_index_.Get(), reinterpret_cast<void*>(NULL)); + ThreadData* current_thread_data = new ThreadData(suggested_name); tls_index_.Set(current_thread_data); } @@ -183,7 +172,7 @@ ThreadData* ThreadData::Get() { // We must be a worker thread, since we didn't pre-register. ThreadData* worker_thread_data = NULL; { - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); if (!unregistered_thread_data_pool_->empty()) { worker_thread_data = const_cast<ThreadData*>(unregistered_thread_data_pool_->top()); @@ -214,13 +203,13 @@ void ThreadData::OnThreadTerminationCleanup() const { tls_index_.Set(NULL); if (!is_a_worker_thread_) return; - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); unregistered_thread_data_pool_->push(this); } // static void ThreadData::WriteHTML(const std::string& query, std::string* output) { - if (!ThreadData::tracking_status()) + if (!ThreadData::IsActive()) return; // Not yet initialized. DataCollector collected_data; // Gather data. @@ -327,12 +316,13 @@ void ThreadData::WriteHTMLTotalAndSubtotals( } // static -base::DictionaryValue* ThreadData::ToValue() { +base::Value* ThreadData::ToValue(int process_type) { DataCollector collected_data; // Gather data. collected_data.AddListOfLivingObjects(); // Add births that are still alive. base::ListValue* list = collected_data.ToValue(); base::DictionaryValue* dictionary = new base::DictionaryValue(); dictionary->Set("list", list); + dictionary->SetInteger("process", process_type); return dictionary; } @@ -352,8 +342,8 @@ Births* ThreadData::TallyABirth(const Location& location) { } void ThreadData::TallyADeath(const Births& birth, - const Duration& queue_duration, - const Duration& run_duration) { + const TimeDelta& queue_duration, + const TimeDelta& run_duration) { DeathMap::iterator it = death_map_.find(&birth); DeathData* death_data; if (it != death_map_.end()) { @@ -370,7 +360,7 @@ Births* ThreadData::TallyABirthIfActive(const Location& location) { if (!kTrackAllTaskObjects) return NULL; // Not compiled in. - if (!tracking_status()) + if (!IsActive()) return NULL; ThreadData* current_thread_data = Get(); if (!current_thread_data) @@ -379,74 +369,37 @@ Births* ThreadData::TallyABirthIfActive(const Location& location) { } // static -void ThreadData::TallyRunOnNamedThreadIfTracking( - const base::TrackingInfo& completed_task, - const TrackedTime& start_of_run, - const TrackedTime& end_of_run) { +void ThreadData::TallyADeathIfActive(const Births* birth, + const base::TimeTicks& time_posted, + const base::TimeTicks& delayed_start_time, + const base::TimeTicks& start_of_run, + const base::TimeTicks& end_of_run) { if (!kTrackAllTaskObjects) return; // Not compiled in. - // Even if we have been DEACTIVATED, we will process any pending births so - // that our data structures (which counted the outstanding births) remain - // consistent. - const Births* birth = completed_task.birth_tally; - if (!birth) + if (!IsActive() || !birth) return; + ThreadData* current_thread_data = Get(); if (!current_thread_data) return; // To avoid conflating our stats with the delay duration in a PostDelayedTask, // we identify such tasks, and replace their post_time with the time they - // were scheduled (requested?) to emerge from the delayed task queue. This + // were sechudled (requested?) to emerge from the delayed task queue. This // means that queueing delay for such tasks will show how long they went // unserviced, after they *could* be serviced. This is the same stat as we // have for non-delayed tasks, and we consistently call it queueing delay. - TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() - ? tracked_objects::TrackedTime(completed_task.time_posted) - : tracked_objects::TrackedTime(completed_task.delayed_run_time); - - Duration queue_duration = start_of_run - effective_post_time; - Duration run_duration = end_of_run - start_of_run; - current_thread_data->TallyADeath(*birth, queue_duration, run_duration); -} - -// static -void ThreadData::TallyRunOnWorkerThreadIfTracking( - const Births* birth, - const TrackedTime& time_posted, - const TrackedTime& start_of_run, - const TrackedTime& end_of_run) { - if (!kTrackAllTaskObjects) - return; // Not compiled in. - - // Even if we have been DEACTIVATED, we will process any pending births so - // that our data structures (which counted the outstanding births) remain - // consistent. - if (!birth) - return; - - // TODO(jar): Support the option to coalesce all worker-thread activity under - // one ThreadData instance that uses locks to protect *all* access. This will - // reduce memory (making it provably bounded), but run incrementally slower - // (since we'll use locks on TallyBirth and TallyDeath). The good news is - // that the locks on TallyDeath will be *after* the worker thread has run, and - // hence nothing will be waiting for the completion (... besides some other - // thread that might like to run). Also, the worker threads tasks are - // generally longer, and hence the cost of the lock may perchance be amortized - // over the long task's lifetime. - ThreadData* current_thread_data = Get(); - if (!current_thread_data) - return; - - Duration queue_duration = start_of_run - time_posted; - Duration run_duration = end_of_run - start_of_run; + base::TimeTicks effective_post_time = + (delayed_start_time.is_null()) ? time_posted : delayed_start_time; + base::TimeDelta queue_duration = start_of_run - effective_post_time; + base::TimeDelta run_duration = end_of_run - start_of_run; current_thread_data->TallyADeath(*birth, queue_duration, run_duration); } // static ThreadData* ThreadData::first() { - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); return all_thread_data_list_head_; } @@ -486,47 +439,52 @@ void ThreadData::Reset() { it->second->Clear(); } -bool ThreadData::Initialize() { +// static +bool ThreadData::StartTracking(bool status) { if (!kTrackAllTaskObjects) return false; // Not compiled in. - if (status_ != UNINITIALIZED) - return true; - // Initialize all leaking constants that are difficult to toggle in and out - // of existance. - // First call must be made when single threaded at startup. - // Perform the "real" TLS initialization now, and leave it intact through + + // Do a bit of class initialization. + if (!unregistered_thread_data_pool_) { + ThreadDataPool* initial_pool = new ThreadDataPool; + { + base::AutoLock lock(list_lock_); + if (!unregistered_thread_data_pool_) { + unregistered_thread_data_pool_ = initial_pool; + initial_pool = NULL; + } + } + delete initial_pool; // In case it was not used. + } + + // Perform the "real" initialization now, and leave it intact through // process termination. - if (!tls_index_.initialized()) // Testing may have initialized this. + if (!tls_index_.initialized()) tls_index_.Initialize(&ThreadData::OnThreadTermination); DCHECK(tls_index_.initialized()); - unregistered_thread_data_pool_ = new ThreadDataPool; - // TODO(jar): A linker initialized spin lock would be much safer than this - // allocation, which relies on being called while single threaded. - if (!list_lock_) // In case testing deleted this. - list_lock_ = new base::Lock; - status_ = kInitialStartupState; - return true; -} -// static -bool ThreadData::InitializeAndSetTrackingStatus(bool status) { - if (!Initialize()) // No-op if already initialized. - return false; // Not compiled in. - - status_ = status ? ACTIVE : DEACTIVATED; + if (!status) { + base::AutoLock lock(list_lock_); + DCHECK(status_ == ACTIVE || status_ == SHUTDOWN); + status_ = SHUTDOWN; + return true; + } + base::AutoLock lock(list_lock_); + DCHECK_EQ(UNINITIALIZED, status_); + status_ = ACTIVE; return true; } // static -bool ThreadData::tracking_status() { +bool ThreadData::IsActive() { return status_ == ACTIVE; } // static -TrackedTime ThreadData::Now() { - if (!kTrackAllTaskObjects || status_ != ACTIVE) - return TrackedTime(); // Super fast when disabled, or not compiled. - return TrackedTime::Now(); +base::TimeTicks ThreadData::Now() { + if (kTrackAllTaskObjects && status_ == ACTIVE) + return base::TimeTicks::Now(); + return base::TimeTicks(); // Super fast when disabled, or not compiled in. } // static @@ -534,12 +492,12 @@ void ThreadData::ShutdownSingleThreadedCleanup() { // This is only called from test code, where we need to cleanup so that // additional tests can be run. // We must be single threaded... but be careful anyway. - if (!InitializeAndSetTrackingStatus(false)) + if (!StartTracking(false)) return; ThreadData* thread_data_list; ThreadDataPool* final_pool; { - base::AutoLock lock(*list_lock_); + base::AutoLock lock(list_lock_); thread_data_list = all_thread_data_list_head_; all_thread_data_list_head_ = NULL; final_pool = unregistered_thread_data_pool_; @@ -616,12 +574,16 @@ base::DictionaryValue* Snapshot::ToValue() const { return dictionary; } +void Snapshot::Add(const Snapshot& other) { + death_data_.AddDeathData(other.death_data_); +} + //------------------------------------------------------------------------------ // DataCollector DataCollector::DataCollector() { - if (!kTrackAllTaskObjects) - return; // Not compiled in. + if (!ThreadData::IsActive()) + return; // Get an unchanging copy of a ThreadData list. ThreadData* my_list = ThreadData::first(); @@ -778,35 +740,6 @@ void Comparator::Clear() { selector_ = NIL; } -// static -Comparator::Selector Comparator::FindSelector(const std::string& keyword) { - // Sorting and aggretation keywords, which specify how to sort the data, or - // can specify a required match from the specified field in the record. - if (0 == keyword.compare("count")) - return COUNT; - if (0 == keyword.compare("totalduration")) - return TOTAL_RUN_DURATION; - if (0 == keyword.compare("duration")) - return AVERAGE_RUN_DURATION; - if (0 == keyword.compare("totalqueueduration")) - return TOTAL_QUEUE_DURATION; - if (0 == keyword.compare("averagequeueduration")) - return AVERAGE_QUEUE_DURATION; - if (0 == keyword.compare("birth")) - return BIRTH_THREAD; - if (0 == keyword.compare("death")) - return DEATH_THREAD; - if (0 == keyword.compare("file")) - return BIRTH_FILE; - if (0 == keyword.compare("function")) - return BIRTH_FUNCTION; - if (0 == keyword.compare("line")) - return BIRTH_LINE; - if (0 == keyword.compare("reset")) - return RESET_ALL_DATA; - return UNKNOWN_KEYWORD; -} - bool Comparator::operator()(const Snapshot& left, const Snapshot& right) const { switch (selector_) { @@ -1023,6 +956,28 @@ void Comparator::SetSubgroupTiebreaker(Selector selector) { } void Comparator::ParseKeyphrase(const std::string& key_phrase) { + typedef std::map<const std::string, Selector> KeyMap; + static KeyMap key_map; + static bool initialized = false; + if (!initialized) { + initialized = true; + // Sorting and aggretation keywords, which specify how to sort the data, or + // can specify a required match from the specified field in the record. + key_map["count"] = COUNT; + key_map["totalduration"] = TOTAL_RUN_DURATION; + key_map["duration"] = AVERAGE_RUN_DURATION; + key_map["totalqueueduration"] = TOTAL_QUEUE_DURATION; + key_map["averagequeueduration"] = AVERAGE_QUEUE_DURATION; + key_map["birth"] = BIRTH_THREAD; + key_map["death"] = DEATH_THREAD; + key_map["file"] = BIRTH_FILE; + key_map["function"] = BIRTH_FUNCTION; + key_map["line"] = BIRTH_LINE; + + // Immediate commands that do not involve setting sort order. + key_map["reset"] = RESET_ALL_DATA; + } + std::string required; // Watch for: "sort_key=value" as we parse. size_t equal_offset = key_phrase.find('=', 0); @@ -1032,14 +987,13 @@ void Comparator::ParseKeyphrase(const std::string& key_phrase) { } std::string keyword(key_phrase.substr(0, equal_offset)); keyword = StringToLowerASCII(keyword); - Selector selector = FindSelector(keyword); - if (selector == UNKNOWN_KEYWORD) - return; - if (selector == RESET_ALL_DATA) { + KeyMap::iterator it = key_map.find(keyword); + if (key_map.end() == it) + return; // Unknown keyword. + if (it->second == RESET_ALL_DATA) ThreadData::ResetAllThreadData(); - return; - } - SetTiebreaker(selector, required); + else + SetTiebreaker(key_map[keyword], required); } bool Comparator::ParseQuery(const std::string& query) { diff --git a/base/tracked_objects.h b/base/tracked_objects.h index b243da9..1593991 100644 --- a/base/tracked_objects.h +++ b/base/tracked_objects.h @@ -16,13 +16,8 @@ #include "base/time.h" #include "base/synchronization/lock.h" #include "base/threading/thread_local_storage.h" -#include "base/tracking_info.h" #include "base/values.h" -#if defined(OS_WIN) -#include <mmsystem.h> // Declare timeGetTime(); -#endif - // TrackedObjects provides a database of stats about objects (generally Tasks) // that are tracked. Tracking means their birth, death, duration, birth thread, // death thread, and birth place are recorded. This data is carefully spread @@ -74,7 +69,7 @@ // any locks, as all that data is constant across the life of the process. // // The above work *could* also be done for any other object as well by calling -// TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. +// TallyABirthIfActive() and TallyADeathIfActive() as appropriate. // // The amount of memory used in the above data structures depends on how many // threads there are, and how many Locations of construction there are. @@ -172,96 +167,6 @@ class MessageLoop; namespace tracked_objects { //------------------------------------------------------------------------------ - -#define USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS - -#if defined(USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS) - -// TimeTicks maintains a wasteful 64 bits of data (we need less than 32), and on -// windows, a 64 bit timer is expensive to even obtain. We use a simple -// millisecond counter for most of our time values, as well as millisecond units -// of duration between those values. This means we can only handle durations -// up to 49 days (range), or 24 days (non-negative time durations). -// We only define enough methods to service the needs of the tracking classes, -// and our interfaces are modeled after what TimeTicks and TimeDelta use (so we -// can swap them into place if we want to use the "real" classes). - -class BASE_EXPORT Duration { // Similar to base::TimeDelta. - public: - Duration() : ms_(0) {} - - Duration& operator+=(const Duration& other) { - ms_ += other.ms_; - return *this; - } - - Duration operator+(const Duration& other) const { - return Duration(ms_ + other.ms_); - } - - bool operator==(const Duration& other) const { return ms_ == other.ms_; } - bool operator!=(const Duration& other) const { return ms_ != other.ms_; } - bool operator>(const Duration& other) const { return ms_ > other.ms_; } - - static Duration FromMilliseconds(int ms) { return Duration(ms); } - - int32 InMilliseconds() const { return ms_; } - - private: - friend class TrackedTime; - explicit Duration(int32 duration) : ms_(duration) {} - - // Internal time is stored directly in milliseconds. - int32 ms_; -}; - -class BASE_EXPORT TrackedTime { // Similar to base::TimeTicks. - public: - TrackedTime() : ms_(0) {} - explicit TrackedTime(const base::TimeTicks& time) - : ms_((time - base::TimeTicks()).InMilliseconds()) { - } - - static TrackedTime Now() { -#if defined(OS_WIN) - // Use lock-free accessor to 32 bit time. - // Note that TimeTicks::Now() is built on this, so we have "compatible" - // times when we down-convert a TimeTicks sample. - // TODO(jar): Surface this interface via something in base/time.h. - return TrackedTime(static_cast<int32>(::timeGetTime())); -#else - // Posix has nice cheap 64 bit times, so we just down-convert it. - return TrackedTime(base::TimeTicks::Now()); -#endif // OS_WIN - } - - Duration operator-(const TrackedTime& other) const { - return Duration(ms_ - other.ms_); - } - - TrackedTime operator+(const Duration& other) const { - return TrackedTime(ms_ + other.ms_); - } - - bool is_null() const { return ms_ == 0; } - - private: - friend class Duration; - explicit TrackedTime(int32 ms) : ms_(ms) {} - - // Internal duration is stored directly in milliseconds. - uint32 ms_; -}; - -#else - -// Just use full 64 bit time calculations, and the slower TimeTicks::Now(). -typedef base::TimeTicks TrackedTime; -typedef base::TimeDelta Duration; - -#endif // USE_FAST_TIME_CLASS_FOR_DURATION_CALCULATIONS - -//------------------------------------------------------------------------------ // For a specific thread, and a specific birth place, the collection of all // death info (with tallies for each death thread, to prevent access conflicts). class ThreadData; @@ -312,8 +217,8 @@ class BASE_EXPORT Births: public BirthOnThread { }; //------------------------------------------------------------------------------ -// Basic info summarizing multiple destructions of a tracked object with a -// single birthplace (fixed Location). Used both on specific threads, and also +// Basic info summarizing multiple destructions of an object with a single +// birthplace (fixed Location). Used both on specific threads, and also used // in snapshots when integrating assembled data. class BASE_EXPORT DeathData { @@ -328,14 +233,14 @@ class BASE_EXPORT DeathData { // Update stats for a task destruction (death) that had a Run() time of // |duration|, and has had a queueing delay of |queue_duration|. - void RecordDeath(const Duration& queue_duration, - const Duration& run_duration); + void RecordDeath(const base::TimeDelta& queue_duration, + const base::TimeDelta& run_duration); // Metrics accessors. int count() const { return count_; } - Duration run_duration() const { return run_duration_; } + base::TimeDelta run_duration() const { return run_duration_; } int AverageMsRunDuration() const; - Duration queue_duration() const { return queue_duration_; } + base::TimeDelta queue_duration() const { return queue_duration_; } int AverageMsQueueDuration() const; // Accumulate metrics from other into this. This method is never used on @@ -345,7 +250,7 @@ class BASE_EXPORT DeathData { // Simple print of internal state for use in line of HTML. void WriteHTML(std::string* output) const; - // Construct a DictionaryValue instance containing all our stats. The caller + // Constructe a DictionaryValue instance containing all our stats. The caller // assumes ownership of the returned instance. base::DictionaryValue* ToValue() const; @@ -354,8 +259,8 @@ class BASE_EXPORT DeathData { private: int count_; // Number of destructions. - Duration run_duration_; // Sum of all Run()time durations. - Duration queue_duration_; // Sum of all queue time durations. + base::TimeDelta run_duration_; // Sum of all Run()time durations. + base::TimeDelta queue_duration_; // Sum of all queue time durations. }; //------------------------------------------------------------------------------ @@ -382,11 +287,13 @@ class BASE_EXPORT Snapshot { const std::string DeathThreadName() const; int count() const { return death_data_.count(); } - Duration run_duration() const { return death_data_.run_duration(); } - Duration queue_duration() const { return death_data_.queue_duration(); } + base::TimeDelta run_duration() const { return death_data_.run_duration(); } int AverageMsRunDuration() const { return death_data_.AverageMsRunDuration(); } + base::TimeDelta queue_duration() const { + return death_data_.queue_duration(); + } int AverageMsQueueDuration() const { return death_data_.AverageMsQueueDuration(); } @@ -398,6 +305,8 @@ class BASE_EXPORT Snapshot { // The caller assumes ownership of the memory in the returned instance. base::DictionaryValue* ToValue() const; + void Add(const Snapshot& other); + private: const BirthOnThread* birth_; // Includes Location and birth_thread. const ThreadData* death_thread_; @@ -417,23 +326,20 @@ class BASE_EXPORT DataCollector { DataCollector(); ~DataCollector(); - // Adds all stats from the indicated thread into our arrays. This function - // uses locks at the lowest level (when accessing the underlying maps which - // could change when not locked), and can be called from any threads. + // Add all stats from the indicated thread into our arrays. This function is + // mutex protected, and *could* be called from any threads (although current + // implementation serialized calls to Append). void Append(const ThreadData& thread_data); // After the accumulation phase, the following accessor is used to process the - // data (i.e., sort it, filter it, etc.). + // data. Collection* collection(); - // Adds entries for all the remaining living objects (objects that have - // tallied a birth, but have not yet tallied a matching death, and hence must - // be either running, queued up, or being held in limbo for future posting). - // This should be called after all known ThreadData instances have been - // processed using Append(). + // After collection of death data is complete, we can add entries for all the + // remaining living objects. void AddListOfLivingObjects(); - // Generates a ListValue representation of the vector of snapshots. The caller + // Generate a ListValue representation of the vector of snapshots. The caller // assumes ownership of the memory in the returned instance. base::ListValue* ToValue() const; @@ -444,8 +350,7 @@ class BASE_EXPORT DataCollector { Collection collection_; // The total number of births recorded at each location for which we have not - // seen a death count. This map changes as we do Append() calls, and is later - // used by AddListOfLivingObjects() to gather up unaccounted for births. + // seen a death count. BirthCount global_birth_count_; DISALLOW_COPY_AND_ASSIGN(DataCollector); @@ -454,9 +359,6 @@ class BASE_EXPORT DataCollector { //------------------------------------------------------------------------------ // Aggregation contains summaries (totals and subtotals) of groups of Snapshot // instances to provide printing of these collections on a single line. -// We generally provide an aggregate total for the entire list, as well as -// aggregate subtotals for groups of stats (example: group of all lives that -// died on the specific thread). class BASE_EXPORT Aggregation: public DeathData { public: @@ -512,7 +414,6 @@ class BASE_EXPORT Comparator { // Imediate action keywords. RESET_ALL_DATA = -1, - UNKNOWN_KEYWORD = -2, }; explicit Comparator(); @@ -569,10 +470,6 @@ class BASE_EXPORT Comparator { // members of the tested elements. enum Selector selector_; - // Translate a path keyword into a selector. This is a slow implementation, - // but this is rarely done, and only for HTML presentations. - static Selector FindSelector(const std::string& keyword); - // For filtering into acceptable and unacceptable snapshot instance, the // following is required to be a substring of the selector_ field. std::string required_; @@ -596,27 +493,16 @@ class BASE_EXPORT Comparator { //------------------------------------------------------------------------------ // For each thread, we have a ThreadData that stores all tracking info generated // on this thread. This prevents the need for locking as data accumulates. -// We use ThreadLocalStorage to quickly identfy the current ThreadData context. -// We also have a linked list of ThreadData instances, and that list is used to -// harvest data from all existing instances. class BASE_EXPORT ThreadData { public: - // Current allowable states of the tracking system. The states can vary - // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. - enum Status { - UNINITIALIZED, - ACTIVE, - DEACTIVATED, - }; - typedef std::map<Location, Births*> BirthMap; typedef std::map<const Births*, DeathData> DeathMap; // Initialize the current thread context with a new instance of ThreadData. - // This is used by all threads that have names, and should be explicitly - // set *before* any births on the threads have taken place. It is generally - // only used by the message loop, which has a well defined thread name. + // This is used by all threads that have names, and can be explicitly + // set *before* any births are threads have taken place. It is generally + // only used by the message loop, which has a well defined name. static void InitializeThreadContext(const std::string& suggested_name); // Using Thread Local Store, find the current instance for collecting data. @@ -629,47 +515,33 @@ class BASE_EXPORT ThreadData { // append to output. static void WriteHTML(const std::string& query, std::string* output); + // Constructe a ListValue instance containing all recursive results in our + // process. The caller assumes ownership of the memory in the returned + // instance. The |process_type| should become an enum, which corresponds + // to all possible process types. I'm using an int as a placeholder. + static base::Value* ToValue(int process_type); + // For a given accumulated array of results, use the comparator to sort and // subtotal, writing the results to the output. static void WriteHTMLTotalAndSubtotals( const DataCollector::Collection& match_array, const Comparator& comparator, std::string* output); - // Constructs a DictionaryValue instance containing all recursive results in - // our process. The caller assumes ownership of the memory in the returned - // instance. - static base::DictionaryValue* ToValue(); - - // Finds (or creates) a place to count births from the given location in this + // Find (or create) a place to count births from the given location in this // thread, and increment that tally. // TallyABirthIfActive will returns NULL if the birth cannot be tallied. static Births* TallyABirthIfActive(const Location& location); - // Records the end of a timed run of an object. The |completed_task| contains - // a pointer to a Births, the time_posted, and a delayed_start_time if any. - // The |start_of_run| indicates when we started to perform the run of the - // task. The delayed_start_time is non-null for tasks that were posted as - // delayed tasks, and it indicates when the task should have run (i.e., when - // it should have posted out of the timer queue, and into the work queue. - // The |end_of_run| was just obtained by a call to Now() (just after the task - // finished). It is provided as an argument to help with testing. - static void TallyRunOnNamedThreadIfTracking( - const base::TrackingInfo& completed_task, - const TrackedTime& start_of_run, - const TrackedTime& end_of_run); - // Record the end of a timed run of an object. The |birth| is the record for - // the instance, the |time_posted| records that instant, which is presumed to - // be when the task was posted into a queue to run on a worker thread. - // The |start_of_run| is when the worker thread started to perform the run of - // the task. + // the instance, the |time_posted| and |start_of_run| are times of posting + // into a message loop queue, and of starting to perform the run of the task. // The |end_of_run| was just obtained by a call to Now() (just after the task // finished). - static void TallyRunOnWorkerThreadIfTracking( - const Births* birth, - const TrackedTime& time_posted, - const TrackedTime& start_of_run, - const TrackedTime& end_of_run); + static void TallyADeathIfActive(const Births* birth, + const base::TimeTicks& time_posted, + const base::TimeTicks& delayed_start_time, + const base::TimeTicks& start_of_run, + const base::TimeTicks& end_of_run); const std::string thread_name() const { return thread_name_; } @@ -695,21 +567,17 @@ class BASE_EXPORT ThreadData { // bogus counts VERY rarely. static void ResetAllThreadData(); - // Initializes all statics if needed (this initialization call should be made - // while we are single threaded). Returns false if unable to initialize. - static bool Initialize(); - - // Sets internal status_ to either become ACTIVE, or DEACTIVATED, + // Set internal status_ to either become ACTIVE, or later, to be SHUTDOWN, // based on argument being true or false respectively. - // If tracking is not compiled in, this function will return false. - static bool InitializeAndSetTrackingStatus(bool status); - static bool tracking_status(); + // IF tracking is not compiled in, this function will return false. + static bool StartTracking(bool status); + static bool IsActive(); // Provide a time function that does nothing (runs fast) when we don't have // the profiler enabled. It will generally be optimized away when it is // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of // the code). - static TrackedTime Now(); + static base::TimeTicks Now(); // WARNING: ONLY call this function when you are running single threaded // (again) and all message loops and threads have terminated. Until that @@ -719,6 +587,14 @@ class BASE_EXPORT ThreadData { static void ShutdownSingleThreadedCleanup(); private: + // Current allowable states of the tracking system. The states always + // proceed towards SHUTDOWN, and never go backwards. + enum Status { + UNINITIALIZED, + ACTIVE, + SHUTDOWN, + }; + typedef std::stack<const ThreadData*> ThreadDataPool; // Worker thread construction creates a name since there is none. @@ -738,8 +614,8 @@ class BASE_EXPORT ThreadData { // Find a place to record a death on this thread. void TallyADeath(const Births& birth, - const Duration& queue_duration, - const Duration& duration); + const base::TimeDelta& queue_duration, + const base::TimeDelta& duration); // Using our lock to protect the iteration, Clear all birth and death data. void Reset(); @@ -764,8 +640,8 @@ class BASE_EXPORT ThreadData { // pool, and if none are available, construct a new one. static ThreadDataPool* unregistered_thread_data_pool_; // Protection for access to all_thread_data_list_head_, and to - // unregistered_thread_data_pool_. This lock is leaked at shutdown. - static base::Lock* list_lock_; + // unregistered_thread_data_pool_. + static base::Lock list_lock_; // We set status_ to SHUTDOWN when we shut down the tracking service. static Status status_; @@ -819,17 +695,21 @@ class BASE_EXPORT ThreadData { class BASE_EXPORT AutoTracking { public: AutoTracking() { - ThreadData::Initialize(); + if (state_ != kNeverBeenRun) + return; + ThreadData::StartTracking(true); + state_ = kRunning; } ~AutoTracking() { - // TODO(jar): Consider emitting a CSV dump of the data at this point. This - // should be called after the message loops have all terminated (or at least - // the main message loop is gone), so there is little chance for additional - // tasks to be Run. } private: + enum State { + kNeverBeenRun, + kRunning, + }; + static State state_; DISALLOW_COPY_AND_ASSIGN(AutoTracking); }; diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc index b457cb1..ef88183 100644 --- a/base/tracked_objects_unittest.cc +++ b/base/tracked_objects_unittest.cc @@ -15,18 +15,15 @@ namespace tracked_objects { class TrackedObjectsTest : public testing::Test { public: - TrackedObjectsTest() { - ThreadData::ShutdownSingleThreadedCleanup(); - } + ~TrackedObjectsTest() { + ThreadData::ShutdownSingleThreadedCleanup(); + } - ~TrackedObjectsTest() { - ThreadData::ShutdownSingleThreadedCleanup(); - } }; TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { // Minimal test doesn't even create any tasks. - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. @@ -44,7 +41,7 @@ TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { ThreadData::ShutdownSingleThreadedCleanup(); // Do it again, just to be sure we reset state completely. - ThreadData::InitializeAndSetTrackingStatus(true); + ThreadData::StartTracking(true); EXPECT_FALSE(ThreadData::first()); // No activity even on this thread. data = ThreadData::Get(); EXPECT_TRUE(ThreadData::first()); // Now class was constructed. @@ -60,7 +57,7 @@ TEST_F(TrackedObjectsTest, MinimalStartupShutdown) { } TEST_F(TrackedObjectsTest, TinyStartupShutdown) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // Instigate tracking on a single tracked object, on our thread. @@ -80,14 +77,14 @@ TEST_F(TrackedObjectsTest, TinyStartupShutdown) { EXPECT_EQ(0u, death_map.size()); // No deaths. - // Now instigate another birth, and a first death at the same location. - // TrackingInfo will call TallyABirth() during construction. - base::TimeTicks kBogusStartTime; - base::TrackingInfo pending_task(location, kBogusStartTime); - TrackedTime kBogusStartRunTime; - TrackedTime kBogusEndRunTime; - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, kBogusStartRunTime, - kBogusEndRunTime); + // Now instigate a birth, and a death. + const Births* second_birth = ThreadData::TallyABirthIfActive(location); + ThreadData::TallyADeathIfActive( + second_birth, + base::TimeTicks(), /* Bogus post_time. */ + base::TimeTicks(), /* Bogus delayed_start_time. */ + base::TimeTicks(), /* Bogus start_run_time. */ + base::TimeTicks() /* Bogus end_run_time */ ); birth_map.clear(); data->SnapshotBirthMap(&birth_map); @@ -103,13 +100,13 @@ TEST_F(TrackedObjectsTest, TinyStartupShutdown) { } TEST_F(TrackedObjectsTest, DeathDataTest) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; scoped_ptr<DeathData> data(new DeathData()); ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); - EXPECT_EQ(data->run_duration(), Duration()); - EXPECT_EQ(data->queue_duration(), Duration()); + EXPECT_EQ(data->run_duration(), base::TimeDelta()); + EXPECT_EQ(data->queue_duration(), base::TimeDelta()); EXPECT_EQ(data->AverageMsRunDuration(), 0); EXPECT_EQ(data->AverageMsQueueDuration(), 0); EXPECT_EQ(data->count(), 0); @@ -117,8 +114,8 @@ TEST_F(TrackedObjectsTest, DeathDataTest) { int run_ms = 42; int queue_ms = 8; - Duration run_duration = Duration().FromMilliseconds(run_ms); - Duration queue_duration = Duration().FromMilliseconds(queue_ms); + base::TimeDelta run_duration = base::TimeDelta().FromMilliseconds(run_ms); + base::TimeDelta queue_duration = base::TimeDelta().FromMilliseconds(queue_ms); data->RecordDeath(queue_duration, run_duration); EXPECT_EQ(data->run_duration(), run_duration); EXPECT_EQ(data->queue_duration(), queue_duration); @@ -154,69 +151,20 @@ TEST_F(TrackedObjectsTest, DeathDataTest) { EXPECT_EQ(json, birth_only_result); } -TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueWorkerThread) { - // Transition to Deactivated state before doing anything. - if (!ThreadData::InitializeAndSetTrackingStatus(false)) - return; - // We don't initialize system with a thread name, so we're viewed as a worker - // thread. - const int kFakeLineNumber = 173; - const char* kFile = "FixedFileName"; - const char* kFunction = "BirthOnlyToValueWorkerThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - Births* birth = ThreadData::TallyABirthIfActive(location); - // We should now see a NULL birth record. - EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); - std::string json; - base::JSONWriter::Write(value.get(), false, &json); - std::string birth_only_result = "{" - "\"list\":[" - "]" - "}"; - EXPECT_EQ(json, birth_only_result); -} - -TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToValueMainThread) { - // Start in the deactivated state. - if (!ThreadData::InitializeAndSetTrackingStatus(false)) - return; - - // Use a well named thread. - ThreadData::InitializeThreadContext("SomeMainThreadName"); - const int kFakeLineNumber = 173; - const char* kFile = "FixedFileName"; - const char* kFunction = "BirthOnlyToValueMainThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - // Do not delete birth. We don't own it. - Births* birth = ThreadData::TallyABirthIfActive(location); - // We expect to not get a birth record. - EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); - std::string json; - base::JSONWriter::Write(value.get(), false, &json); - std::string birth_only_result = "{" - "\"list\":[" - "]" - "}"; - EXPECT_EQ(json, birth_only_result); -} - TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // We don't initialize system with a thread name, so we're viewed as a worker // thread. - const int kFakeLineNumber = 173; + int fake_line_number = 173; const char* kFile = "FixedFileName"; const char* kFunction = "BirthOnlyToValueWorkerThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); + Location location(kFunction, kFile, fake_line_number, NULL); Births* birth = ThreadData::TallyABirthIfActive(location); EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - scoped_ptr<base::Value> value(ThreadData::ToValue()); + int process_type = 3; + scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); std::string json; base::JSONWriter::Write(value.get(), false, &json); std::string birth_only_result = "{" @@ -235,26 +183,28 @@ TEST_F(TrackedObjectsTest, BirthOnlyToValueWorkerThread) { "\"line_number\":173" "}" "}" - "]" + "]," + "\"process\":3" "}"; EXPECT_EQ(json, birth_only_result); } TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // Use a well named thread. ThreadData::InitializeThreadContext("SomeMainThreadName"); - const int kFakeLineNumber = 173; + int fake_line_number = 173; const char* kFile = "FixedFileName"; const char* kFunction = "BirthOnlyToValueMainThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); + Location location(kFunction, kFile, fake_line_number, NULL); // Do not delete birth. We don't own it. Births* birth = ThreadData::TallyABirthIfActive(location); EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - scoped_ptr<base::Value> value(ThreadData::ToValue()); + int process_type = 34; + scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); std::string json; base::JSONWriter::Write(value.get(), false, &json); std::string birth_only_result = "{" @@ -273,39 +223,40 @@ TEST_F(TrackedObjectsTest, BirthOnlyToValueMainThread) { "\"line_number\":173" "}" "}" - "]" + "]," + "\"process\":34" "}"; EXPECT_EQ(json, birth_only_result); } TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // Use a well named thread. ThreadData::InitializeThreadContext("SomeMainThreadName"); - const int kFakeLineNumber = 236; + int fake_line_number = 236; const char* kFile = "FixedFileName"; const char* kFunction = "LifeCycleToValueMainThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); + Location location(kFunction, kFile, fake_line_number, NULL); // Do not delete birth. We don't own it. Births* birth = ThreadData::TallyABirthIfActive(location); EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - const base::TimeTicks kTimePosted = base::TimeTicks() - + base::TimeDelta::FromMilliseconds(1); - const base::TimeTicks kDelayedStartTime = base::TimeTicks(); - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task(location, kDelayedStartTime); - pending_task.time_posted = kTimePosted; // Overwrite implied Now(). - - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - kStartOfRun, kEndOfRun); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); + // TimeTicks initializers ar ein microseconds. Durations are calculated in + // milliseconds, so we need to use 1000x. + const base::TimeTicks time_posted = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(1); + const base::TimeTicks delayed_start_time = base::TimeTicks(); + const base::TimeTicks start_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(5); + const base::TimeTicks end_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(7); + ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, + start_of_run, end_of_run); + + int process_type = 7; + scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); std::string json; base::JSONWriter::Write(value.get(), false, &json); std::string one_line_result = "{" @@ -324,190 +275,44 @@ TEST_F(TrackedObjectsTest, LifeCycleToValueMainThread) { "\"line_number\":236" "}" "}" - "]" + "]," + "\"process\":7" "}"; - EXPECT_EQ(one_line_result, json); -} - -// We will deactivate tracking after the birth, and before the death, and -// demonstrate that the lifecycle is completely tallied. This ensures that -// our tallied births are matched by tallied deaths (except for when the -// task is still running, or is queued). -TEST_F(TrackedObjectsTest, LifeCycleMidDeactivatedToValueMainThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) - return; - - // Use a well named thread. - ThreadData::InitializeThreadContext("SomeMainThreadName"); - const int kFakeLineNumber = 236; - const char* kFile = "FixedFileName"; - const char* kFunction = "LifeCycleToValueMainThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - // Do not delete birth. We don't own it. - Births* birth = ThreadData::TallyABirthIfActive(location); - EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - - const base::TimeTicks kTimePosted = base::TimeTicks() - + base::TimeDelta::FromMilliseconds(1); - const base::TimeTicks kDelayedStartTime = base::TimeTicks(); - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task(location, kDelayedStartTime); - pending_task.time_posted = kTimePosted; // Overwrite implied Now(). - - // Turn off tracking now that we have births. - EXPECT_TRUE(ThreadData::InitializeAndSetTrackingStatus(false)); - - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - kStartOfRun, kEndOfRun); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); - std::string json; - base::JSONWriter::Write(value.get(), false, &json); - std::string one_line_result = "{" - "\"list\":[" - "{" - "\"birth_thread\":\"SomeMainThreadName\"," - "\"death_data\":{" - "\"count\":1," - "\"queue_ms\":4," - "\"run_ms\":2" - "}," - "\"death_thread\":\"SomeMainThreadName\"," - "\"location\":{" - "\"file_name\":\"FixedFileName\"," - "\"function_name\":\"LifeCycleToValueMainThread\"," - "\"line_number\":236" - "}" - "}" - "]" - "}"; - EXPECT_EQ(one_line_result, json); -} - -// We will deactivate tracking before starting a life cycle, and neither -// the birth nor the death will be recorded. -TEST_F(TrackedObjectsTest, LifeCyclePreDeactivatedToValueMainThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(false)) - return; - - // Use a well named thread. - ThreadData::InitializeThreadContext("SomeMainThreadName"); - const int kFakeLineNumber = 236; - const char* kFile = "FixedFileName"; - const char* kFunction = "LifeCycleToValueMainThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - // Do not delete birth. We don't own it. - Births* birth = ThreadData::TallyABirthIfActive(location); - EXPECT_EQ(birth, reinterpret_cast<Births*>(NULL)); - - const base::TimeTicks kTimePosted = base::TimeTicks() - + base::TimeDelta::FromMilliseconds(1); - const base::TimeTicks kDelayedStartTime = base::TimeTicks(); - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task(location, kDelayedStartTime); - pending_task.time_posted = kTimePosted; // Overwrite implied Now(). - - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - kStartOfRun, kEndOfRun); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); - std::string json; - base::JSONWriter::Write(value.get(), false, &json); - std::string one_line_result = "{" - "\"list\":[" - "]" - "}"; - EXPECT_EQ(one_line_result, json); -} - -TEST_F(TrackedObjectsTest, LifeCycleToValueWorkerThread) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) - return; - - // Don't initialize thread, so that we appear as a worker thread. - // ThreadData::InitializeThreadContext("SomeMainThreadName"); - - const int kFakeLineNumber = 236; - const char* kFile = "FixedFileName"; - const char* kFunction = "LifeCycleToValueWorkerThread"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - // Do not delete birth. We don't own it. - Births* birth = ThreadData::TallyABirthIfActive(location); - EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - - const TrackedTime kTimePosted = TrackedTime() + Duration::FromMilliseconds(1); - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnWorkerThreadIfTracking(birth, kTimePosted, - kStartOfRun, kEndOfRun); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); - std::string json; - base::JSONWriter::Write(value.get(), false, &json); - std::string one_line_result = "{" - "\"list\":[" - "{" - "\"birth_thread\":\"WorkerThread-1\"," - "\"death_data\":{" - "\"count\":1," - "\"queue_ms\":4," - "\"run_ms\":2" - "}," - "\"death_thread\":\"WorkerThread-1\"," - "\"location\":{" - "\"file_name\":\"FixedFileName\"," - "\"function_name\":\"LifeCycleToValueWorkerThread\"," - "\"line_number\":236" - "}" - "}" - "]" - "}"; - EXPECT_EQ(one_line_result, json); + EXPECT_EQ(json, one_line_result); } TEST_F(TrackedObjectsTest, TwoLives) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // Use a well named thread. ThreadData::InitializeThreadContext("SomeFileThreadName"); - const int kFakeLineNumber = 222; + int fake_line_number = 222; const char* kFile = "AnotherFileName"; const char* kFunction = "TwoLives"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); + Location location(kFunction, kFile, fake_line_number, NULL); // Do not delete birth. We don't own it. Births* birth = ThreadData::TallyABirthIfActive(location); EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - - const base::TimeTicks kTimePosted = base::TimeTicks() - + base::TimeDelta::FromMilliseconds(1); - const base::TimeTicks kDelayedStartTime = base::TimeTicks(); - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task(location, kDelayedStartTime); - pending_task.time_posted = kTimePosted; // Overwrite implied Now(). - - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - kStartOfRun, kEndOfRun); - - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task2(location, kDelayedStartTime); - pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). - - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, - kStartOfRun, kEndOfRun); - - scoped_ptr<base::Value> value(ThreadData::ToValue()); + // TimeTicks initializers ar ein microseconds. Durations are calculated in + // milliseconds, so we need to use 1000x. + const base::TimeTicks time_posted = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(1); + const base::TimeTicks delayed_start_time = base::TimeTicks(); + const base::TimeTicks start_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(5); + const base::TimeTicks end_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(7); + ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, + start_of_run, end_of_run); + + birth = ThreadData::TallyABirthIfActive(location); + ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, + start_of_run, end_of_run); + + int process_type = 7; + scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); std::string json; base::JSONWriter::Write(value.get(), false, &json); std::string one_line_result = "{" @@ -526,43 +331,44 @@ TEST_F(TrackedObjectsTest, TwoLives) { "\"line_number\":222" "}" "}" - "]" + "]," + "\"process\":7" "}"; - EXPECT_EQ(one_line_result, json); + EXPECT_EQ(json, one_line_result); } TEST_F(TrackedObjectsTest, DifferentLives) { - if (!ThreadData::InitializeAndSetTrackingStatus(true)) + if (!ThreadData::StartTracking(true)) return; // Use a well named thread. ThreadData::InitializeThreadContext("SomeFileThreadName"); - const int kFakeLineNumber = 567; + int fake_line_number = 567; const char* kFile = "AnotherFileName"; const char* kFunction = "DifferentLives"; - Location location(kFunction, kFile, kFakeLineNumber, NULL); - - const base::TimeTicks kTimePosted = base::TimeTicks() - + base::TimeDelta::FromMilliseconds(1); - const base::TimeTicks kDelayedStartTime = base::TimeTicks(); - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task(location, kDelayedStartTime); - pending_task.time_posted = kTimePosted; // Overwrite implied Now(). - - const TrackedTime kStartOfRun = TrackedTime() + - Duration::FromMilliseconds(5); - const TrackedTime kEndOfRun = TrackedTime() + Duration::FromMilliseconds(7); - ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, - kStartOfRun, kEndOfRun); - - const int kSecondFakeLineNumber = 999; - Location second_location(kFunction, kFile, kSecondFakeLineNumber, NULL); - - // TrackingInfo will call TallyABirth() during construction. - base::TrackingInfo pending_task2(second_location, kDelayedStartTime); - pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). + Location location(kFunction, kFile, fake_line_number, NULL); + // Do not delete birth. We don't own it. + Births* birth = ThreadData::TallyABirthIfActive(location); + EXPECT_NE(birth, reinterpret_cast<Births*>(NULL)); - scoped_ptr<base::Value> value(ThreadData::ToValue()); + // TimeTicks initializers ar ein microseconds. Durations are calculated in + // milliseconds, so we need to use 1000x. + const base::TimeTicks time_posted = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(1); + const base::TimeTicks delayed_start_time = base::TimeTicks(); + const base::TimeTicks start_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(5); + const base::TimeTicks end_of_run = base::TimeTicks() + + base::TimeDelta::FromMilliseconds(7); + ThreadData::TallyADeathIfActive(birth, time_posted, delayed_start_time, + start_of_run, end_of_run); + + int second_fake_line_number = 999; + Location second_location(kFunction, kFile, second_fake_line_number, NULL); + birth = ThreadData::TallyABirthIfActive(second_location); + + int process_type = 2; + scoped_ptr<base::Value> value(ThreadData::ToValue(process_type)); std::string json; base::JSONWriter::Write(value.get(), false, &json); std::string one_line_result = "{" @@ -595,9 +401,10 @@ TEST_F(TrackedObjectsTest, DifferentLives) { "\"line_number\":999" "}" "}" - "]" + "]," + "\"process\":2" "}"; - EXPECT_EQ(one_line_result, json); + EXPECT_EQ(json, one_line_result); } } // namespace tracked_objects diff --git a/base/tracking_info.cc b/base/tracking_info.cc deleted file mode 100644 index 7ac4221..0000000 --- a/base/tracking_info.cc +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/tracking_info.h" - -#include "base/tracked_objects.h" - -namespace base { - -TrackingInfo::TrackingInfo( - const tracked_objects::Location& posted_from, - base::TimeTicks delayed_run_time) - : birth_tally( - tracked_objects::ThreadData::TallyABirthIfActive(posted_from)), - time_posted(TimeTicks::Now()), - delayed_run_time(delayed_run_time) { -} - -TrackingInfo::~TrackingInfo() {} - -} // namespace base - diff --git a/base/tracking_info.h b/base/tracking_info.h deleted file mode 100644 index 0886fdf..0000000 --- a/base/tracking_info.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This is a simple struct with tracking information that is stored -// with a PendingTask (when message_loop is handling the task). -// Only the information that is shared with the profiler in tracked_objects -// are included in this structure. - - -#ifndef BASE_TRACKING_INFO_H_ -#define BASE_TRACKING_INFO_H_ - -#include "base/time.h" - -namespace tracked_objects { -class Location; -class Births; -} - -namespace base { - -// This structure is copied around by value. -struct BASE_EXPORT TrackingInfo { - TrackingInfo(const tracked_objects::Location& posted_from, - base::TimeTicks delayed_run_time); - ~TrackingInfo(); - - // Record of location and thread that the task came from. - tracked_objects::Births* birth_tally; - - // Time when the related task was posted. - base::TimeTicks time_posted; - - // The time when the task should be run. - base::TimeTicks delayed_run_time; -}; - -} // namespace base - -#endif // BASE_TRACKING_INFO_H_ diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 16d2dcf..8d005b5 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -145,9 +145,11 @@ const char* const kChromePaths[] = { chrome::kChromeUITCMallocHost, chrome::kChromeUITermsHost, chrome::kChromeUITracingHost, - chrome::kChromeUITrackingHost, chrome::kChromeUIVersionHost, chrome::kChromeUIWorkersHost, +#if defined(TRACK_ALL_TASK_OBJECTS) + chrome::kChromeUITrackingHost, +#endif #if defined(OS_WIN) chrome::kChromeUIConflictsHost, #endif @@ -182,8 +184,10 @@ const char* const kAboutSourceNames[] = { chrome::kChromeUIStatsHost, chrome::kChromeUITaskManagerHost, chrome::kChromeUITermsHost, - chrome::kChromeUITrackingHost, chrome::kChromeUIVersionHost, +#if defined(TRACK_ALL_TASK_OBJECTS) + chrome::kChromeUITrackingHost, +#endif #if defined(USE_TCMALLOC) chrome::kChromeUITCMallocHost, #endif @@ -885,6 +889,7 @@ void AboutMemory(const std::string& path, AboutSource* source, int request_id) { } } +#if defined(TRACK_ALL_TASK_OBJECTS) static std::string AboutTracking(const std::string& query) { std::string unescaped_title("About Tracking"); if (!query.empty()) { @@ -898,6 +903,7 @@ static std::string AboutTracking(const std::string& query) { AppendFooter(&data); return data; } +#endif // TRACK_ALL_TASK_OBJECTS // Handler for filling in the "about:stats" page, as called by the browser's // About handler processing. @@ -1468,8 +1474,10 @@ void AboutSource::StartDataRequest(const std::string& path, #endif } else if (host == chrome::kChromeUIStatsHost) { response = AboutStats(path); +#if defined(TRACK_ALL_TASK_OBJECTS) } else if (host == chrome::kChromeUITrackingHost) { response = AboutTracking(path); +#endif #if defined(USE_TCMALLOC) } else if (host == chrome::kChromeUITCMallocHost) { response = AboutTcmalloc(); diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 2d9576f..e74b7ba 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -1217,13 +1217,6 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { browser_process_.reset(new BrowserProcessImpl(parsed_command_line())); } - if (parsed_command_line().HasSwitch(switches::kEnableTracking)) { - std::string flag = - parsed_command_line().GetSwitchValueASCII(switches::kEnableTracking); - if (flag.compare("0") == 0) - tracked_objects::ThreadData::InitializeAndSetTrackingStatus(false); - } - // This forces the TabCloseableStateWatcher to be created and, on chromeos, // register for the notifications it needs to track the closeable state of // tabs. diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h index 5e41c16..817e8de 100644 --- a/chrome/browser/chrome_browser_main.h +++ b/chrome/browser/chrome_browser_main.h @@ -118,10 +118,12 @@ class ChromeBrowserMainParts : public content::BrowserMainParts { // it is destroyed last. scoped_ptr<ShutdownWatcherHelper> shutdown_watcher_; +#if defined(TRACK_ALL_TASK_OBJECTS) // Creating this object starts tracking the creation and deletion of Task // instance. This MUST be done before main_message_loop, so that it is // destroyed after the main_message_loop. tracked_objects::AutoTracking tracking_objects_; +#endif // Statistical testing infrastructure for the entire browser. NULL until // SetupMetricsAndFieldTrials is called. diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index e4db0c6f..06c120b 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -519,12 +519,6 @@ const char kDisablePanels[] = "disable-panels"; // Enables speculative TCP/IP preconnection. const char kEnablePreconnect[] = "enable-preconnect"; -// Controls the support for SDCH filtering (dictionary based expansion of -// content). By default SDCH filtering is enabled. To disable SDCH filtering, -// use "--enable-sdch=0" as command line argument. SDCH is currently only -// supported server-side for searches on google.com. -const char kEnableSdch[] = "enable-sdch"; - // Enables the IsSearchProviderInstalled and InstallSearchProvider with an // extra parameter to indicate if the provider should be the default. const char kEnableSearchProviderApiV2[] = "enable-search-provider-api-v2"; @@ -545,28 +539,21 @@ const char kEnableSyncOAuth[] = "enable-sync-oauth"; const char kEnableSyncSearchEngines[] = "enable-sync-search-engines"; // Enables syncing browser sessions. -const char kEnableSyncTabs[] = "enable-sync-tabs"; +const char kEnableSyncTabs[] = "enable-sync-tabs"; // Enables syncing browser sessions for other synced clients. const char kEnableSyncTabsForOtherClients[] = "enable-sync-tabs-for-other-clients"; // Enable syncing app notifications. -const char kEnableSyncAppNotifications[] = "enable-sync-app-notifications"; +const char kEnableSyncAppNotifications[] = "enable-sync-app-notifications"; // Enables context menu for selecting groups of tabs. -const char kEnableTabGroupsContextMenu[] = "enable-tab-groups-context-menu"; +const char kEnableTabGroupsContextMenu[] = "enable-tab-groups-context-menu"; // Enables the "synced bookmarks" folder. const char kEnableSyncedBookmarksFolder[] = "enable-synced-bookmarks-folder"; -// Enables tracking of tasks in profiler for viewing via about:tracking. -// To predominantly disable tracking (profiling), use the command line switch: -// --enable-tracking=0 -// Some tracking will still take place at startup, but it will be turned off -// during chrome_browser_main. -const char kEnableTracking[] = "enable-tracking"; - // Spawns threads to watch for excessive delays in specified message loops. // User should set breakpoints on Alarm() to examine problematic thread. // @@ -976,6 +963,12 @@ const char kSbDisableAutoUpdate[] = "safebrowsing-disable-auto-update"; const char kSbDisableDownloadProtection[] = "safebrowsing-disable-download-protection"; +// Controls the support for SDCH filtering (dictionary based expansion of +// content). By default SDCH filtering is enabled. To disable SDCH filtering, +// use "--enable-sdch=0" as command line argument. SDCH is currently only +// supported server-side for searches on google.com. +const char kEnableSdch[] = "enable-sdch"; + // Enables the showing of an info-bar instructing user they can search directly // from the omnibox. const char kSearchInOmniboxHint[] = "search-in-omnibox-hint"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 31bee61..19a09d8 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -148,7 +148,6 @@ extern const char kEnableNTPBookmarkFeatures[]; extern const char kDisablePanels[]; extern const char kEnablePreconnect[]; extern const char kEnableResourceContentSettings[]; -extern const char kEnableSdch[]; extern const char kEnableSearchProviderApiV2[]; extern const char kEnableShortcutsProvider[]; extern const char kEnableSmoothScrolling[]; @@ -161,7 +160,6 @@ extern const char kEnableSyncTabs[]; extern const char kEnableSyncTabsForOtherClients[]; extern const char kEnableSyncAppNotifications[]; extern const char kEnableSyncedBookmarksFolder[]; -extern const char kEnableTracking[]; extern const char kEnableTabGroupsContextMenu[]; extern const char kEnableTopSites[]; extern const char kEnableWatchdog[]; @@ -264,6 +262,7 @@ extern const char kSbInfoURLPrefix[]; extern const char kSbMacKeyURLPrefix[]; extern const char kSbDisableAutoUpdate[]; extern const char kSbDisableDownloadProtection[]; +extern const char kEnableSdch[]; extern const char kSearchInOmniboxHint[]; extern const char kServiceAccountLsid[]; extern const char kShowAutofillTypePredictions[]; diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 63f6faf..ff12449 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -292,7 +292,10 @@ void BrowserMainLoop::InitializeMainThread() { const char* kThreadName = "CrBrowserMain"; base::PlatformThread::SetName(kThreadName); main_message_loop_->set_thread_name(kThreadName); + +#if defined(TRACK_ALL_TASK_OBJECTS) tracked_objects::ThreadData::InitializeThreadContext(kThreadName); +#endif // TRACK_ALL_TASK_OBJECTS // Register the main thread by instantiating it, but don't call any methods. main_thread_.reset(new BrowserThreadImpl(BrowserThread::UI, |