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

Unified Diff: base/tracked_objects.h

Issue 8894022: Detect child tasks born during a profiled tasks (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/tracked_objects.h
===================================================================
--- base/tracked_objects.h (revision 113750)
+++ base/tracked_objects.h (working copy)
@@ -7,6 +7,7 @@
#pragma once
#include <map>
+#include <set>
#include <stack>
#include <string>
#include <vector>
@@ -198,6 +199,12 @@
const Location location() const;
const ThreadData* birth_thread() const;
+ // Insert our state (location, and thread name) into the dictionary.
+ // Use the supplied |prefix| in frost of "thread_name" and "location"
+ // respectively when defining keys.
+ void ToValue(const std::string& prefix,
+ base::DictionaryValue* dictionary) const;
+
private:
// File/lineno of birth. This defines the essence of the task, as the context
// of the birth (construction) often tell what the item is for. This field
@@ -305,7 +312,8 @@
class BASE_EXPORT Snapshot {
public:
// When snapshotting a full life cycle set (birth-to-death), use this:
- Snapshot(const BirthOnThread& birth_on_thread, const ThreadData& death_thread,
+ Snapshot(const BirthOnThread& birth_on_thread,
+ const ThreadData& death_thread,
const DeathData& death_data);
// When snapshotting a birth, with no death yet, use this:
@@ -336,13 +344,18 @@
// 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,
+ UNINITIALIZED, // PRistine, link-time state before running.
+ DORMANT_DURING_TESTS, // Only used during testing.
+ DEACTIVATED, // No longer recordin profling.
+ PROFILING_ACTIVE, // Recording profiles, but not parent-child links.
+ FULLY_ACTIVE, // Fully active, recording parent-child links.
};
typedef std::map<Location, Births*> BirthMap;
typedef std::map<const Births*, DeathData> DeathMap;
+ typedef std::pair<const Births*, const Births*> ParentChildPair;
+ typedef std::set<ParentChildPair> ParentChildSet;
+ typedef std::stack<const Births*> ParentStack;
// Initialize the current thread context with a new instance of ThreadData.
// This is used by all threads that have names, and should be explicitly
@@ -403,9 +416,9 @@
const std::string thread_name() const;
// 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.
+ // each set of maps (BirthMap, DeathMap, and ParentChildSet) 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
@@ -418,17 +431,33 @@
// while we are single threaded). Returns false if unable to initialize.
static bool Initialize();
- // Sets internal status_ to either become ACTIVE, or DEACTIVATED,
- // based on argument being true or false respectively.
+ // Sets internal status_.
+ // If |status| is false, then status_ is set to DEACTIVATED.
+ // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or
+ // FULLY_ACTIVE.
// If tracking is not compiled in, this function will return false.
+ // If parent-child tracking is not compiled in, then an attempt to set the
+ // status to FULLY_ACTIVE will only result in a status of PROFILING_ACTIVE
+ // (i.e., it can't be set to a higher level than what is compiled into the
+ // binary, and parent-child tracking at the FULLY_ACTIVE level might not be
+ // compiled in).
static bool InitializeAndSetTrackingStatus(bool status);
+
+ // Indicate if any sort of profiling is being done (i.e., we are more than
+ // DEACTIVATED).
static bool tracking_status();
+ // For testing only, indicate if the status of parent-child tracking is turned
+ // on. This is currently a compiled option, atop tracking_status().
+ static bool tracking_parent_child_status();
+
// Special versions of Now() for getting times at start and end of a tracked
// run. They are super fast when tracking is disabled, and have some internal
// side effects when we are tracking, so that we can deduce the amount of time
// accumulated outside of execution of tracked runs.
- static TrackedTime NowForStartOfRun();
+ // The task that will be tracked is passed in as |parent| so that parent-child
+ // relationships can be (optionally) calculated.
+ static TrackedTime NowForStartOfRun(const Births* parent);
static TrackedTime NowForEndOfRun();
// Provide a time function that does nothing (runs fast) when we don't have
@@ -451,6 +480,7 @@
friend class TrackedObjectsTest;
FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown);
FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown);
+ FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest);
// Worker thread construction creates a name since there is none.
explicit ThreadData(int thread_number);
@@ -487,7 +517,8 @@
// zero in the active DeathMap (not the snapshot).
void SnapshotMaps(bool reset_max,
BirthMap* birth_map,
- DeathMap* death_map);
+ DeathMap* death_map,
+ ParentChildSet* parent_child_set);
// Using our lock to protect the iteration, Clear all birth and death data.
void Reset();
@@ -546,12 +577,6 @@
static base::LazyInstance<base::Lock,
base::LeakyLazyInstanceTraits<base::Lock> > list_lock_;
- // Record of what the incarnation_counter_ was when this instance was created.
- // If the incarnation_counter_ has changed, then we avoid pushing into the
- // pool (this is only critical in tests which go through multiple
- // incarations).
- int incarnation_count_for_pool_;
-
// We set status_ to SHUTDOWN when we shut down the tracking service.
static Status status_;
@@ -587,6 +612,11 @@
// locking before reading it.
DeathMap death_map_;
+ // A set of parents that created children tasks on this thread. Each pair
+ // correnponds to potentially non local Births (location and thread), and a
+ // local Births (that took place on this thread).
+ ParentChildSet parent_child_set_;
+
// Lock to protect *some* access to BirthMap and DeathMap. The maps are
// regularly read and written on this thread, but may only be read from other
// threads. To support this, we acquire this lock if we are writing from this
@@ -595,12 +625,28 @@
// writing is only done from this thread.
mutable base::Lock map_lock_;
+ // The stack of parents that are currently being profiled. This includes only
+ // tasks that have started a timer recently via NowForStartOfRun(), but not
+ // yet concluded with a NowForEndOfRun(). Usually this stack is one deep, but
+ // if a scoped region is profiled, or <sigh> a task runs a nested-message
+ // loop, then the stack can grow larger. Note that we don't try to deduct
+ // time in nested porfiles, as our current timer is based on wall-clock time,
+ // and not CPU time (and we're hopeful that nested timing won't be a
+ // significant additional cost).
+ ParentStack parent_stack_;
+
// 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_;
+ // Record of what the incarnation_counter_ was when this instance was created.
+ // If the incarnation_counter_ has changed, then we avoid pushing into the
+ // pool (this is only critical in tests which go through multiple
+ // incarations).
+ int incarnation_count_for_pool_;
+
DISALLOW_COPY_AND_ASSIGN(ThreadData);
};
@@ -621,8 +667,9 @@
// 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);
+ const ThreadData::BirthMap& birth_map,
+ const ThreadData::DeathMap& death_map,
+ const ThreadData::ParentChildSet& parent_child_set);
// After the accumulation phase, the following accessor is used to process the
// data (i.e., sort it, filter it, etc.).
@@ -637,7 +684,7 @@
// Generates a ListValue representation of the vector of snapshots. The caller
// assumes ownership of the memory in the returned instance.
- base::ListValue* ToValue() const;
+ void ToValue(base::DictionaryValue* dictionary) const;
private:
typedef std::map<const BirthOnThread*, int> BirthCount;
@@ -650,6 +697,9 @@
// used by AddListOfLivingObjects() to gather up unaccounted for births.
BirthCount global_birth_count_;
+ // The complete list of parent-child relatioships among tasks.
+ ThreadData::ParentChildSet parent_child_set_;
+
DISALLOW_COPY_AND_ASSIGN(DataCollector);
};

Powered by Google App Engine
This is Rietveld 408576698