summaryrefslogtreecommitdiffstats
path: root/base/tracked_objects.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/tracked_objects.h')
-rw-r--r--base/tracked_objects.h263
1 files changed, 121 insertions, 142 deletions
diff --git a/base/tracked_objects.h b/base/tracked_objects.h
index 29b2900..1eca68b 100644
--- a/base/tracked_objects.h
+++ b/base/tracked_objects.h
@@ -12,6 +12,7 @@
#include <vector>
#include "base/base_export.h"
+#include "base/gtest_prod_util.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/profiler/tracked_time.h"
@@ -197,8 +198,8 @@ class BASE_EXPORT BirthOnThread {
public:
BirthOnThread(const Location& location, const ThreadData& current);
- const Location location() const { return location_; }
- const ThreadData* birth_thread() const { return birth_thread_; }
+ const Location location() const;
+ const ThreadData* birth_thread() const;
private:
// File/lineno of birth. This defines the essence of the task, as the context
@@ -220,17 +221,17 @@ class BASE_EXPORT Births: public BirthOnThread {
public:
Births(const Location& location, const ThreadData& current);
- int birth_count() const { return birth_count_; }
+ int birth_count() const;
// When we have a birth we update the count for this BirhPLace.
- void RecordBirth() { ++birth_count_; }
+ void RecordBirth();
// When a birthplace is changed (updated), we need to decrement the counter
// for the old instance.
- void ForgetBirth() { --birth_count_; } // We corrected a birth place.
+ void ForgetBirth();
// Hack to quickly reset all counts to zero.
- void Clear() { birth_count_ = 0; }
+ void Clear();
private:
// The number of births on this thread for our location_.
@@ -247,70 +248,49 @@ class BASE_EXPORT Births: public BirthOnThread {
class BASE_EXPORT DeathData {
public:
// Default initializer.
- DeathData() : count_(0) {}
+ DeathData();
// When deaths have not yet taken place, and we gather data from all the
// threads, we create DeathData stats that tally the number of births without
- // a corrosponding death.
- explicit DeathData(int count)
- : count_(count) {}
+ // a corresponding death.
+ explicit DeathData(int count);
// 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(DurationInt queue_duration,
- DurationInt run_duration);
-
- // Metrics accessors.
- int count() const { return count_; }
- DurationInt run_duration() const { return run_time_.duration(); }
- DurationInt AverageMsRunDuration() const;
- DurationInt run_duration_max() const { return run_time_.max(); }
- DurationInt queue_duration() const { return queue_time_.duration(); }
- DurationInt AverageMsQueueDuration() const;
- DurationInt queue_duration_max() const { return queue_time_.max(); }
-
- // Accumulate metrics from other into this. This method is never used on
- // realtime statistics, and only used in snapshots and aggregatinos.
- void AddDeathData(const DeathData& other);
+ void RecordDeath(const DurationInt queue_duration,
+ const DurationInt run_duration,
+ int random_number);
+
+ // Metrics accessors, used only in tests.
+ int count() const;
+ DurationInt run_duration_sum() const;
+ DurationInt run_duration_max() const;
+ DurationInt run_duration_sample() const;
+ DurationInt queue_duration_sum() const;
+ DurationInt queue_duration_max() const;
+ DurationInt queue_duration_sample() const;
// Construct a DictionaryValue instance containing all our stats. The caller
// assumes ownership of the returned instance.
base::DictionaryValue* ToValue() const;
+ // Reset the max values to zero.
+ void ResetMax();
+
// Reset all tallies to zero. This is used as a hack on realtime data.
void Clear();
private:
- // DeathData::Data is a helper class, useful when different metrics need to be
- // aggregated, such as queueing times, or run times.
- class Data {
- public:
- Data() : duration_(0), max_(0) {}
- ~Data() {}
-
- DurationInt duration() const { return duration_; }
- DurationInt max() const { return max_; }
-
- // Agggegate data into our state.
- void AddData(const Data& other);
- void AddDuration(DurationInt duration);
-
- // Central helper function for calculating averages (correctly, in only one
- // place).
- DurationInt AverageMsDuration(int count) const;
-
- // Resets all members to zero.
- void Clear();
-
- private:
- DurationInt duration_; // Sum of all durations seen.
- DurationInt max_; // Largest singular duration seen.
- };
-
-
- int count_; // Number of deaths seen.
- Data run_time_; // Data about run time durations.
- Data queue_time_; // Data about queueing times durations.
+ // Number of runs seen.
+ int count_;
+ // Data about run time durations.
+ DurationInt run_duration_sum_;
+ DurationInt run_duration_max_;
+ DurationInt run_duration_sample_;
+ // Data about queueing times durations.
+ DurationInt queue_duration_sum_;
+ DurationInt queue_duration_max_;
+ DurationInt queue_duration_sample_;
};
//------------------------------------------------------------------------------
@@ -329,29 +309,9 @@ class BASE_EXPORT Snapshot {
// When snapshotting a birth, with no death yet, use this:
Snapshot(const BirthOnThread& birth_on_thread, int count);
- const ThreadData* birth_thread() const { return birth_->birth_thread(); }
- const Location location() const { return birth_->location(); }
- const BirthOnThread& birth() const { return *birth_; }
- const ThreadData* death_thread() const {return death_thread_; }
- const DeathData& death_data() const { return death_data_; }
+ // Accessor, that provides default value when there is no death thread.
const std::string DeathThreadName() const;
- int count() const { return death_data_.count(); }
- DurationInt run_duration() const { return death_data_.run_duration(); }
- DurationInt AverageMsRunDuration() const {
- return death_data_.AverageMsRunDuration();
- }
- DurationInt run_duration_max() const {
- return death_data_.run_duration_max();
- }
- DurationInt queue_duration() const { return death_data_.queue_duration(); }
- DurationInt AverageMsQueueDuration() const {
- return death_data_.AverageMsQueueDuration();
- }
- DurationInt queue_duration_max() const {
- return death_data_.queue_duration_max();
- }
-
// Construct a DictionaryValue instance containing all our data recursively.
// The caller assumes ownership of the memory in the returned instance.
base::DictionaryValue* ToValue() const;
@@ -363,53 +323,6 @@ class BASE_EXPORT Snapshot {
};
//------------------------------------------------------------------------------
-// DataCollector is a container class for Snapshot and BirthOnThread count
-// items.
-
-class BASE_EXPORT DataCollector {
- public:
- typedef std::vector<Snapshot> Collection;
-
- // Construct with a list of how many threads should contribute. This helps us
- // determine (in the async case) when we are done with all contributions.
- 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.
- 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.).
- 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().
- void AddListOfLivingObjects();
-
- // Generates a ListValue representation of the vector of snapshots. The caller
- // assumes ownership of the memory in the returned instance.
- base::ListValue* ToValue() const;
-
- private:
- typedef std::map<const BirthOnThread*, int> BirthCount;
-
- // The array that we collect data into.
- 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.
- BirthCount global_birth_count_;
-
- DISALLOW_COPY_AND_ASSIGN(DataCollector);
-};
-
-//------------------------------------------------------------------------------
// 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.
@@ -443,8 +356,9 @@ class BASE_EXPORT ThreadData {
// 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();
+ // instance. During the scavenging, if |reset_max| is true, then the
+ // DeathData instances max-values are reset to zero during this scan.
+ static base::DictionaryValue* ToValue(bool reset_max);
// Finds (or creates) a place to count births from the given location in this
// thread, and increment that tally.
@@ -484,24 +398,13 @@ class BASE_EXPORT ThreadData {
const TrackedTime& start_of_run,
const TrackedTime& end_of_run);
- const std::string thread_name() const { return thread_name_; }
+ const std::string thread_name() const;
- // ---------------------
- // TODO(jar):
- // The following functions should all be private, and are only public because
- // the collection is done externally. We need to relocate that code from the
- // collection class into this class, and then all these methods can be made
- // private.
- // (Thread safe) Get start of list of all ThreadData instances.
- static ThreadData* first();
- // Iterate through the null terminated list of ThreadData instances.
- ThreadData* next() const { return next_; }
- // Using our lock, make a copy of the specified maps. These calls may arrive
- // from non-local threads, and are used to quickly scan data from all threads
- // in order to build JSON for about:profiler.
- void SnapshotBirthMap(BirthMap *output) const;
- void SnapshotDeathMap(DeathMap *output) const;
- // -------- end of should be private methods.
+ // Snapshot (under a lock) copies of the maps in each ThreadData instance. For
+ // each set of maps (BirthMap and DeathMap) call the Append() method of the
+ // |target| DataCollector. If |reset_max| is true, then the max values in
+ // each DeathData instance should be reset during the scan.
+ static void SendAllMaps(bool reset_max, class DataCollector* target);
// Hack: asynchronously clear all birth counts and death tallies data values
// in all ThreadData instances. The numerical (zeroing) part is done without
@@ -540,7 +443,12 @@ class BASE_EXPORT ThreadData {
private:
// Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it
// in production code.
+ // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a
+ // better change of optimizing (inlining? etc.) private methods (knowing that
+ // there will be no need for an external entry point).
friend class TrackedObjectsTest;
+ FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown);
+ FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown);
// Worker thread construction creates a name since there is none.
explicit ThreadData(int thread_number);
@@ -555,6 +463,13 @@ class BASE_EXPORT ThreadData {
// the instance permanently on that list.
void PushToHeadOfList();
+ // (Thread safe) Get start of list of all ThreadData instances using the lock.
+ static ThreadData* first();
+
+ // Iterate through the null terminated list of ThreadData instances.
+ ThreadData* next() const;
+
+
// In this thread's data, record a new birth.
Births* TallyABirth(const Location& location);
@@ -563,6 +478,15 @@ class BASE_EXPORT ThreadData {
DurationInt queue_duration,
DurationInt duration);
+ // Using our lock, make a copy of the specified maps. This call may be made
+ // on non-local threads, which necessitate the use of the lock to prevent
+ // the map(s) from being reallocaed while they are copied. If |reset_max| is
+ // true, then, just after we copy the DeathMap, we will set the max values to
+ // zero in the active DeathMap (not the snapshot).
+ void SnapshotMaps(bool reset_max,
+ BirthMap* birth_map,
+ DeathMap* death_map);
+
// Using our lock to protect the iteration, Clear all birth and death data.
void Reset();
@@ -669,10 +593,65 @@ class BASE_EXPORT ThreadData {
// writing is only done from this thread.
mutable base::Lock map_lock_;
+ // A random number that we used to select decide which sample to keep as a
+ // representative sample in each DeathData instance. We can't start off with
+ // much randomness (because we can't call RandInt() on all our threads), so
+ // we stir in more and more as we go.
+ int32 random_number_;
+
DISALLOW_COPY_AND_ASSIGN(ThreadData);
};
//------------------------------------------------------------------------------
+// DataCollector is a container class for Snapshot and BirthOnThread count
+// items.
+
+class BASE_EXPORT DataCollector {
+ public:
+ typedef std::vector<Snapshot> Collection;
+
+ // Construct with a list of how many threads should contribute. This helps us
+ // determine (in the async case) when we are done with all contributions.
+ DataCollector();
+ ~DataCollector();
+
+ // Adds all stats from the indicated thread into our arrays. Accepts copies
+ // of the birth_map and death_map, so that the data will not change during the
+ // iterations and processing.
+ void Append(const ThreadData &thread_data,
+ const ThreadData::BirthMap &birth_map,
+ const ThreadData::DeathMap &death_map);
+
+ // After the accumulation phase, the following accessor is used to process the
+ // data (i.e., sort it, filter it, etc.).
+ 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().
+ void AddListOfLivingObjects();
+
+ // Generates a ListValue representation of the vector of snapshots. The caller
+ // assumes ownership of the memory in the returned instance.
+ base::ListValue* ToValue() const;
+
+ private:
+ typedef std::map<const BirthOnThread*, int> BirthCount;
+
+ // The array that we collect data into.
+ 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.
+ BirthCount global_birth_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(DataCollector);
+};
+
+//------------------------------------------------------------------------------
// Provide simple way to to start global tracking, and to tear down tracking
// when done. The design has evolved to *not* do any teardown (and just leak
// all allocated data structures). As a result, we don't have any code in this