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

Unified Diff: base/tracked_objects.h

Issue 8597017: Switch to a simple linked-list for worker thread pool (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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
« no previous file with comments | « no previous file | base/tracked_objects.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/tracked_objects.h
===================================================================
--- base/tracked_objects.h (revision 110706)
+++ base/tracked_objects.h (working copy)
@@ -137,8 +137,10 @@
//
// A DataCollector is a container object that holds a set of Snapshots. The
// statistics in a snapshot are gathered asynhcronously relative to their
-// ongoing updates. It is possible, though highly unlikely, that stats such
-// as a 64bit counter could be incorrectly recorded by this process. The
+// ongoing updates. It is possible, though highly unlikely, that stats could be
+// incorrectly recorded by this process (all data is held in 32 bit ints, but we
+// are not atomically collecting all data, so we could have count that does not,
+// for example, match with the number of durations we accumulated). The
// advantage to having fast (non-atomic) updates of the data outweighs the
// minimal risk of a singular corrupt statistic snapshot (only the snapshot
// could be corrupt, not the underlying and ongoing statistic). In constrast,
@@ -148,23 +150,40 @@
//
// After an array of Snapshots instances are collected into a DataCollector,
// they need to be prepared for displaying our output. We currently implement a
-// direct rendering to HTML, but we will soon have a JSON serialization as well.
-
-// For direct HTML display, the data must be sorted, and possibly aggregated
-// (example: how many threads are in a specific consecutive set of Snapshots?
-// What was the total birth count for that set? etc.). Aggregation instances
-// collect running sums of any set of snapshot instances, and are used to print
-// sub-totals in an about:profiler page.
+// serialization into a Value hierarchy, which is automatically translated to
+// JSON when supplied to rendering Java Scirpt.
//
-// TODO(jar): I need to store DataCollections, and provide facilities for taking
-// the difference between two gathered DataCollections. For now, I'm just
-// adding a hack that Reset()s to zero all counts and stats. This is also
+// TODO(jar): We can implement a Snapshot system that *tries* to grab the
+// snapshots on the source threads *when* they have MessageLoops available
+// (worker threads don't have message loops generally, and hence gathering from
+// them will continue to be asynchronous). We had an implementation of this in
+// the past, but the difficulty is dealing with message loops being terminated.
+// We can *try* to spam the available threads via some message loop proxy to
+// achieve this feat, and it *might* be valuable when we are colecting data for
+// upload via UMA (where correctness of data may be more significant than for a
+// single screen of about:profiler).
+//
+// TODO(jar): We need to save a single sample in each DeathData instance of the
+// times recorded. This sample should be selected in a uniformly random way.
+//
+// TODO(jar): We should support (optionally) the recording of of parent-child
ramant (doing other things) 2011/11/18 23:33:44 nit: of of -> of
jar (doing other things) 2011/11/18 23:57:41 Done.
+// relationships for tasks. This should be done by detecting what tasks are
+// Born during the running of a parent task. The resulting data can be used by
+// a smarter profiler to aggregate the cost of a series of child tasks into
+// the ancestor task. It can also be used to illuminate what child or parent is
+// related to each task.
+//
+// TODO(jar): We need to store DataCollections, and provide facilities for
+// taking the difference between two gathered DataCollections. For now, we're
+// just adding a hack that Reset()s to zero all counts and stats. This is also
// done in a slighly thread-unsafe fashion, as the resetting is done
// asynchronously relative to ongoing updates (but all data is 32 bit in size).
// For basic profiling, this will work "most of the time," and should be
// sufficient... but storing away DataCollections is the "right way" to do this.
// We'll accomplish this via JavaScript storage of snapshots, and then we'll
-// remove the Reset() methods.
+// remove the Reset() methods. We may also need a short-term-max value in
+// DeathData that is reset (as synchronously as possible) during each snapshot.
+// This will facilitate displaying a max value for each snapshot period.
class MessageLoop;
@@ -254,9 +273,6 @@
// realtime statistics, and only used in snapshots and aggregatinos.
void AddDeathData(const DeathData& other);
- // 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
// assumes ownership of the returned instance.
base::DictionaryValue* ToValue() const;
@@ -275,10 +291,6 @@
DurationInt duration() const { return duration_; }
DurationInt max() const { return max_; }
- // Emits HTML formated description of members, assuming |count| instances
- // when calculating averages.
- void WriteHTML(int count, std::string* output) const;
-
// Agggegate data into our state.
void AddData(const Data& other);
void AddDuration(DurationInt duration);
@@ -486,7 +498,7 @@
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 an HTML page for about:profiler.
+ // in order to build JSON for about:profiler.
void SnapshotBirthMap(BirthMap *output) const;
void SnapshotDeathMap(DeathMap *output) const;
// -------- end of should be private methods.
@@ -525,30 +537,8 @@
// in production code.
friend class TrackedObjectsTest;
- // Implment a stack that avoids allocations during a push() by having enough
- // space ahead of time.
- class ThreadDataPool {
- public:
- ThreadDataPool();
- ~ThreadDataPool();
-
- // Make sure the stack is large enough to support the indicated number of
- // elements.
- void reserve(size_t largest_worker_pool_number);
-
- bool empty() const;
- const ThreadData* top() const;
- void push(const ThreadData* thread_data);
- void pop();
-
- private:
- std::vector<const ThreadData*> stack_;
- size_t empty_slot_;
- DISALLOW_COPY_AND_ASSIGN(ThreadDataPool);
- };
-
// Worker thread construction creates a name since there is none.
- explicit ThreadData(size_t thread_number);
+ explicit ThreadData(int thread_number);
// Message loop based construction should provide a name.
explicit ThreadData(const std::string& suggested_name);
@@ -577,7 +567,7 @@
// This method should be called when a worker thread terminates, so that we
// can save all the thread data into a cache of reusable ThreadData instances.
- void OnThreadTerminationCleanup() const;
+ void OnThreadTerminationCleanup();
// Cleans up data structures, and returns statics to near pristine (mostly
// uninitialized) state. If there is any chance that other threads are still
@@ -593,16 +583,17 @@
// We use thread local store to identify which ThreadData to interact with.
static base::ThreadLocalStorage::Slot tls_index_;
+ // List of ThreadData instances for use with worker threads. When a worker
+ // thread is done (terminated), we push it onto this llist. When a new worker
+ // thread is created, we first try to re-use a ThreadData instance from the
+ // list, and if none are available, construct a new one.
+ // This is only accessed while list_lock_ is held.
+ static ThreadData* first_retired_worker_;
+
// Link to the most recently created instance (starts a null terminated list).
// The list is traversed by about:profiler when it needs to snapshot data.
// This is only accessed while list_lock_ is held.
static ThreadData* all_thread_data_list_head_;
- // Set of ThreadData instances for use with worker threads. When a worker
- // thread is done (terminating), we push it into this pool. When a new worker
- // thread is created, we first try to re-use a ThreadData instance from the
- // pool, and if none are available, construct a new one.
- // This is only accessed while list_lock_ is held.
- static ThreadDataPool* unregistered_thread_data_pool_;
// The next available thread number. This should only be accessed when the
// list_lock_ is held.
static int thread_number_counter_;
@@ -631,6 +622,11 @@
// data).
ThreadData* next_;
+ // Pointer to another ThreadData instance for a Worker-Thread that has been
+ // retired (its thread was terminated). This value is non-NULL only for a
+ // retired ThreadData associated with a Worker-Thread.
+ ThreadData* next_retired_worker_;
+
// The name of the thread that is being recorded. If this thread has no
// message_loop, then this is a worker thread, with a sequence number postfix.
std::string thread_name_;
@@ -639,7 +635,7 @@
// stored in the unregistered_thread_data_pool_ when not in use.
// Value is zero when it is not a worker thread. Value is a positive integer
// corresponding to the created thread name if it is a worker thread.
- size_t worker_thread_number_;
+ int worker_thread_number_;
// A map used on each thread to keep track of Births on this thread.
// This map should only be accessed on the thread it was constructed on.
« no previous file with comments | « no previous file | base/tracked_objects.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698