15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_TRACKED_OBJECTS_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_TRACKED_OBJECTS_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stack> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h" 1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/basictypes.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/profiler/alternate_timer.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/profiler/tracked_time.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_local_storage.h" 2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace base { 2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)struct TrackingInfo; 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TrackedObjects provides a database of stats about objects (generally Tasks) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that are tracked. Tracking means their birth, death, duration, birth thread, 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death thread, and birth place are recorded. This data is carefully spread 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// across a series of objects so that the counts and times can be rapidly 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updated without (usually) having to lock the data, and hence there is usually 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// very little contention caused by the tracking. The data can be viewed via 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the about:profiler URL, with a variety of sorting and filtering choices. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These classes serve as the basis of a profiler of sorts for the Tasks system. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// As a result, design decisions were made to maximize speed, by minimizing 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recurring allocation/deallocation, lock contention and data copying. In the 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "stable" state, which is reached relatively quickly, there is no separate 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// marginal allocation cost associated with construction or destruction of 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// tracked objects, no locks are generally employed, and probably the largest 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// computational cost is associated with obtaining start and stop times for 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances as they are created and destroyed. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following describes the lifecycle of tracking an instance. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// First off, when the instance is created, the FROM_HERE macro is expanded 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to specify the birth place (file, line, function) where the instance was 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// created. That data is used to create a transient Location instance 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// encapsulating the above triple of information. The strings (like __FILE__) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are passed around by reference, with the assumption that they are static, and 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will never go away. This ensures that the strings can be dealt with as atoms 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with great efficiency (i.e., copying of strings is never needed, and 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// comparisons for equality can be based on pointer comparisons). 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Next, a Births instance is created for use ONLY on the thread where this 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance was created. That Births instance records (in a base class 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BirthOnThread) references to the static data provided in a Location instance, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as a pointer specifying the thread on which the birth takes place. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Hence there is at most one Births instance for each Location on each thread. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The derived Births class contains slots for recording statistics about all 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances born at the same location. Statistics currently include only the 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// count of instances constructed. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since the base class BirthOnThread contains only constant data, it can be 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// freely accessed by any thread at any time (i.e., only the statistic needs to 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be handled carefully, and stats are updated exclusively on the birth thread). 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For Tasks, having now either constructed or found the Births instance 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// described above, a pointer to the Births instance is then recorded into the 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PendingTask structure in MessageLoop. This fact alone is very useful in 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// debugging, when there is a question of where an instance came from. In 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// addition, the birth time is also recorded and used to later evaluate the 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lifetime duration of the whole Task. As a result of the above embedding, we 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can find out a Task's location of birth, and thread of birth, without using 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any locks, as all that data is constant across the life of the process. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The above work *could* also be done for any other object as well by calling 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TallyABirthIfActive() and TallyRunOnNamedThreadIfTracking() as appropriate. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The amount of memory used in the above data structures depends on how many 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads there are, and how many Locations of construction there are. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Fortunately, we don't use memory that is the product of those two counts, but 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rather we only need one Births instance for each thread that constructs an 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance at a Location. In many cases, instances are only created on one 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread, so the memory utilization is actually fairly restrained. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lastly, when an instance is deleted, the final tallies of statistics are 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// carefully accumulated. That tallying writes into slots (members) in a 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// collection of DeathData instances. For each birth place Location that is 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destroyed on a thread, there is a DeathData instance to record the additional 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death count, as well as accumulate the run-time and queue-time durations for 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the instance as it is destroyed (dies). By maintaining a single place to 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// aggregate this running sum *only* for the given thread, we avoid the need to 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// lock such DeathData instances. (i.e., these accumulated stats in a DeathData 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance are exclusively updated by the singular owning thread). 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// With the above lifecycle description complete, the major remaining detail is 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// explaining how each thread maintains a list of DeathData instances, and of 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Births instances, and is able to avoid additional (redundant/unnecessary) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocations. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Each thread maintains a list of data items specific to that thread in a 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ThreadData instance (for that specific thread only). The two critical items 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are lists of DeathData and Births instances. These lists are maintained in 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// STL maps, which are indexed by Location. As noted earlier, we can compare 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// locations very efficiently as we consider the underlying data (file, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function, line) to be atoms, and hence pointer comparison is used rather than 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (slow) string comparisons. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To provide a mechanism for iterating over all "known threads," which means 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// threads that have recorded a birth or a death, we create a singly linked list 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of ThreadData instances. Each such instance maintains a pointer to the next 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// one. A static member of ThreadData provides a pointer to the first item on 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this global list, and access via that all_thread_data_list_head_ item 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// requires the use of the list_lock_. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When new ThreadData instances is added to the global list, it is pre-pended, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which ensures that any prior acquisition of the list is valid (i.e., the 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// holder can iterate over it without fear of it changing, or the necessity of 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using an additional lock. Iterations are actually pretty rare (used 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// primarilly for cleanup, or snapshotting data for display), so this lock has 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// very little global performance impact. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The above description tries to define the high performance (run time) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// portions of these classes. After gathering statistics, calls instigated 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by visiting about:profiler will assemble and aggregate data for display. The 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// following data structures are used for producing such displays. They are 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not performance critical, and their only major constraint is that they should 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be able to run concurrently with ongoing augmentation of the birth and death 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This header also exports collection of classes that provide "snapshotted" 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations of the core tracked_objects:: classes. These snapshotted 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// representations are designed for safe transmission of the tracked_objects:: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data across process boundaries. Each consists of: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (1) a default constructor, to support the IPC serialization macros, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (2) a constructor that extracts data from the type being snapshotted, and 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (3) the snapshotted data. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For a given birth location, information about births is spread across data 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// structures that are asynchronously changing on various threads. For 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// serialization and display purposes, we need to construct TaskSnapshot 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instances for each combination of birth thread, death thread, and location, 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// along with the count of such lifetimes. We gather such data into a 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TaskSnapshot instances, so that such instances can be sorted and 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// aggregated (and remain frozen during our processing). 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The ProcessDataSnapshot struct is a serialized representation of the list 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of ThreadData objects for a process. It holds a set of TaskSnapshots 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and tracks parent/child relationships for the executed tasks. The statistics 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a snapshot are gathered asynhcronously relative to their ongoing updates. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is possible, though highly unlikely, that stats could be incorrectly 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// recorded by this process (all data is held in 32 bit ints, but we are not 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// atomically collecting all data, so we could have count that does not, for 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// example, match with the number of durations we accumulated). The advantage 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to having fast (non-atomic) updates of the data outweighs the minimal risk of 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a singular corrupt statistic snapshot (only the snapshot could be corrupt, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not the underlying and ongoing statistic). In constrast, pointer data that 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is accessed during snapshotting is completely invariant, and hence is 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// perfectly acquired (i.e., no potential corruption, and no risk of a bad 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// memory reference). 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We can implement a Snapshot system that *tries* to grab the 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// snapshots on the source threads *when* they have MessageLoops available 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (worker threads don't have message loops generally, and hence gathering from 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// them will continue to be asynchronous). We had an implementation of this in 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the past, but the difficulty is dealing with message loops being terminated. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We can *try* to spam the available threads via some message loop proxy to 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// achieve this feat, and it *might* be valuable when we are colecting data for 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// upload via UMA (where correctness of data may be more significant than for a 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// single screen of about:profiler). 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We should support (optionally) the recording of parent-child 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// relationships for tasks. This should be done by detecting what tasks are 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Born during the running of a parent task. The resulting data can be used by 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a smarter profiler to aggregate the cost of a series of child tasks into 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ancestor task. It can also be used to illuminate what child or parent is 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// related to each task. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(jar): We need to store DataCollections, and provide facilities for 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// taking the difference between two gathered DataCollections. For now, we're 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// just adding a hack that Reset()s to zero all counts and stats. This is also 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// done in a slighly thread-unsafe fashion, as the resetting is done 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// asynchronously relative to ongoing updates (but all data is 32 bit in size). 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For basic profiling, this will work "most of the time," and should be 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sufficient... but storing away DataCollections is the "right way" to do this. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We'll accomplish this via JavaScript storage of snapshots, and then we'll 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// remove the Reset() methods. We may also need a short-term-max value in 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DeathData that is reset (as synchronously as possible) during each snapshot. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This will facilitate displaying a max value for each snapshot period. 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace tracked_objects { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For a specific thread, and a specific birth place, the collection of all 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// death info (with tallies for each death thread, to prevent access conflicts). 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ThreadData; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT BirthOnThread { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThread(const Location& location, const ThreadData& current); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Location location() const { return location_; } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ThreadData* birth_thread() const { return birth_thread_; } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // File/lineno of birth. This defines the essence of the task, as the context 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the birth (construction) often tell what the item is for. This field 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is const, and hence safe to access from any thread. 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Location location_; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The thread that records births into this object. Only this thread is 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allowed to update birth_count_ (which changes over time). 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ThreadData* const birth_thread_; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BirthOnThread); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A "snapshotted" representation of the BirthOnThread class. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT BirthOnThreadSnapshot { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshot(); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit BirthOnThreadSnapshot(const BirthOnThread& birth); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~BirthOnThreadSnapshot(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocationSnapshot location; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string thread_name; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class for accumulating counts of births (without bothering with a map<>). 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT Births: public BirthOnThread { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Births(const Location& location, const ThreadData& current); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int birth_count() const; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When we have a birth we update the count for this birthplace. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RecordBirth(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When a birthplace is changed (updated), we need to decrement the counter 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the old instance. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ForgetBirth(); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hack to quickly reset all counts to zero. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear(); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of births on this thread for our location_. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int birth_count_; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Births); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Basic info summarizing multiple destructions of a tracked object with a 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// single birthplace (fixed Location). Used both on specific threads, and also 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in snapshots when integrating assembled data. 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT DeathData { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default initializer. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathData(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When deaths have not yet taken place, and we gather data from all the 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads, we create DeathData stats that tally the number of births without 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a corresponding death. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit DeathData(int count); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update stats for a task destruction (death) that had a Run() time of 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |duration|, and has had a queueing delay of |queue_duration|. 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RecordDeath(const int32 queue_duration, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int32 run_duration, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int random_number); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Metrics accessors, used only for serialization and in tests. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count() const; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sum() const; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_max() const; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sample() const; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sum() const; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_max() const; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sample() const; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the max values to zero. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResetMax(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset all tallies to zero. This is used as a hack on realtime data. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Clear(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Members are ordered from most regularly read and updated, to least 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frequently used. This might help a bit with cache lines. 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of runs seen (divisor for calculating averages). 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count_; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basic tallies, used to compute averages. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sum_; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sum_; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Max values, used by local visualization routines. These are often read, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but rarely updated. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_max_; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_max_; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Samples, used by crowd sourcing gatherers. These are almost never read, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and rarely updated. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sample_; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sample_; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A "snapshotted" representation of the DeathData class. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT DeathDataSnapshot { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathDataSnapshot(); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit DeathDataSnapshot(const DeathData& death_data); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~DeathDataSnapshot(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sum; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_max; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 run_duration_sample; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sum; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_max; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 queue_duration_sample; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A temporary collection of data that can be sorted and summarized. It is 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gathered (carefully) from many threads. Instances are held in arrays and 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processed, filtered, and rendered. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The source of this data was collected on many threads, and is asynchronously 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// changing. The data in this instance is not asynchronously changing. 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT TaskSnapshot { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskSnapshot(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TaskSnapshot(const BirthOnThread& birth, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DeathData& death_data, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& death_thread_name); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TaskSnapshot(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshot birth; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathDataSnapshot death_data; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string death_thread_name; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For each thread, we have a ThreadData that stores all tracking info generated 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on this thread. This prevents the need for locking as data accumulates. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use ThreadLocalStorage to quickly identfy the current ThreadData context. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We also have a linked list of ThreadData instances, and that list is used to 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// harvest data from all existing instances. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ProcessDataSnapshot; 3551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass BASE_EXPORT TaskStopwatch; 3561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT ThreadData { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Current allowable states of the tracking system. The states can vary 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between ACTIVE and DEACTIVATED, but can never go back to UNINITIALIZED. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Status { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNINITIALIZED, // PRistine, link-time state before running. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DORMANT_DURING_TESTS, // Only used during testing. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEACTIVATED, // No longer recording profling. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROFILING_ACTIVE, // Recording profiles (no parent-child links). 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PROFILING_CHILDREN_ACTIVE, // Fully active, recording parent-child links. 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) STATUS_LAST = PROFILING_CHILDREN_ACTIVE 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<Location, Births*> BirthMap; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<const Births*, DeathData> DeathMap; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::pair<const Births*, const Births*> ParentChildPair; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::set<ParentChildPair> ParentChildSet; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::stack<const Births*> ParentStack; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize the current thread context with a new instance of ThreadData. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is used by all threads that have names, and should be explicitly 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set *before* any births on the threads have taken place. It is generally 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only used by the message loop, which has a well defined thread name. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void InitializeThreadContext(const std::string& suggested_name); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using Thread Local Store, find the current instance for collecting data. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an instance does not exist, construct one (and remember it for use on 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this thread. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This may return NULL if the system is disabled for any reason. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ThreadData* Get(); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fills |process_data| with all the recursive results in our process. 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During the scavenging, if |reset_max| is true, then the DeathData instances 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // max-values are reset to zero during this scan. 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Snapshot(bool reset_max, ProcessDataSnapshot* process_data); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finds (or creates) a place to count births from the given location in this 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, and increment that tally. 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TallyABirthIfActive will returns NULL if the birth cannot be tallied. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Births* TallyABirthIfActive(const Location& location); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Records the end of a timed run of an object. The |completed_task| contains 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a pointer to a Births, the time_posted, and a delayed_start_time if any. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |start_of_run| indicates when we started to perform the run of the 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // task. The delayed_start_time is non-null for tasks that were posted as 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delayed tasks, and it indicates when the task should have run (i.e., when 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it should have posted out of the timer queue, and into the work queue. 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |end_of_run| was just obtained by a call to Now() (just after the task 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // finished). It is provided as an argument to help with testing. 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void TallyRunOnNamedThreadIfTracking( 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TrackingInfo& completed_task, 4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const TaskStopwatch& stopwatch); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the end of a timed run of an object. The |birth| is the record for 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the instance, the |time_posted| records that instant, which is presumed to 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be when the task was posted into a queue to run on a worker thread. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |start_of_run| is when the worker thread started to perform the run of 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the task. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The |end_of_run| was just obtained by a call to Now() (just after the task 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // finished). 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void TallyRunOnWorkerThreadIfTracking( 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Births* birth, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const TrackedTime& time_posted, 4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const TaskStopwatch& stopwatch); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record the end of execution in region, generally corresponding to a scope 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // being exited. 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void TallyRunInAScopedRegionIfTracking( 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Births* birth, 4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const TaskStopwatch& stopwatch); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& thread_name() const { return thread_name_; } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hack: asynchronously clear all birth counts and death tallies data values 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in all ThreadData instances. The numerical (zeroing) part is done without 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use of a locks or atomics exchanges, and may (for int64 values) produce 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bogus counts VERY rarely. 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void ResetAllThreadData(); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes all statics if needed (this initialization call should be made 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while we are single threaded). Returns false if unable to initialize. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool Initialize(); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sets internal status_. 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |status| is false, then status_ is set to DEACTIVATED. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If |status| is true, then status_ is set to, PROFILING_ACTIVE, or 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PROFILING_CHILDREN_ACTIVE. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If tracking is not compiled in, this function will return false. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If parent-child tracking is not compiled in, then an attempt to set the 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // status to PROFILING_CHILDREN_ACTIVE will only result in a status of 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PROFILING_ACTIVE (i.e., it can't be set to a higher level than what is 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compiled into the binary, and parent-child tracking at the 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PROFILING_CHILDREN_ACTIVE level might not be compiled in). 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool InitializeAndSetTrackingStatus(Status status); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Status status(); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicate if any sort of profiling is being done (i.e., we are more than 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DEACTIVATED). 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool TrackingStatus(); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For testing only, indicate if the status of parent-child tracking is turned 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on. This is currently a compiled option, atop TrackingStatus(). 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool TrackingParentChildStatus(); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Marks a start of a tracked run. It's super fast when tracking is disabled, 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // and has some internal side effects when we are tracking, so that we can 4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // deduce the amount of time accumulated outside of execution of tracked runs. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The task that will be tracked is passed in as |parent| so that parent-child 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // relationships can be (optionally) calculated. 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static void PrepareForStartOfRun(const Births* parent); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provide a time function that does nothing (runs fast) when we don't have 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the profiler enabled. It will generally be optimized away when it is 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the code). 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static TrackedTime Now(); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the function |now| to provide current times, instead of calling the 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TrackedTime::Now() function. Since this alternate function is being used, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the other time arguments (used for calculating queueing delay) will be 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ignored. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SetAlternateTimeSource(NowFunction* now); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function can be called at process termination to validate that thread 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cleanup routines have been called for at least some number of named 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads. 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void EnsureCleanupWasCalled(int major_threads_shutdown_count); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci friend class TaskStopwatch; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in production code. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): Make this a friend in DEBUG only, so that the optimizer has a 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // better change of optimizing (inlining? etc.) private methods (knowing that 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // there will be no need for an external entry point). 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class TrackedObjectsTest; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, MinimalStartupShutdown); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, TinyStartupShutdown); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(TrackedObjectsTest, ParentChildTest); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<const BirthOnThread*, int> BirthCountMap; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Worker thread construction creates a name since there is none. 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ThreadData(int thread_number); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Message loop based construction should provide a name. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ThreadData(const std::string& suggested_name); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ThreadData(); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Push this instance to the head of all_thread_data_list_head_, linking it to 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the previous head. This is performed after each construction, and leaves 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the instance permanently on that list. 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PushToHeadOfList(); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (Thread safe) Get start of list of all ThreadData instances using the lock. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ThreadData* first(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate through the null terminated list of ThreadData instances. 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadData* next() const; 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this thread's data, record a new birth. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Births* TallyABirth(const Location& location); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find a place to record a death on this thread. 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void TallyADeath(const Births& birth, 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32 queue_duration, 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const TaskStopwatch& stopwatch); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Snapshot (under a lock) the profiled data for the tasks in each ThreadData 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance. Also updates the |birth_counts| tally for each task to keep 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // track of the number of living instances of the task. If |reset_max| is 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // true, then the max values in each DeathData instance are reset during the 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scan. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void SnapshotAllExecutedTasks(bool reset_max, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDataSnapshot* process_data, 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthCountMap* birth_counts); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Snapshots (under a lock) the profiled data for the tasks for this thread 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and writes all of the executed tasks' data -- i.e. the data for the tasks 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with with entries in the death_map_ -- into |process_data|. Also updates 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the |birth_counts| tally for each task to keep track of the number of 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // living instances of the task -- that is, each task maps to the number of 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // births for the task that have not yet been balanced by a death. If 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |reset_max| is true, then the max values in each DeathData instance are 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset during the scan. 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SnapshotExecutedTasks(bool reset_max, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDataSnapshot* process_data, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthCountMap* birth_counts); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using our lock, make a copy of the specified maps. This call may be made 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on non-local threads, which necessitate the use of the lock to prevent 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the map(s) from being reallocaed while they are copied. If |reset_max| is 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // true, then, just after we copy the DeathMap, we will set the max values to 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // zero in the active DeathMap (not the snapshot). 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SnapshotMaps(bool reset_max, 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthMap* birth_map, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathMap* death_map, 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParentChildSet* parent_child_set); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using our lock to protect the iteration, Clear all birth and death data. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset(); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method is called by the TLS system when a thread terminates. 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The argument may be NULL if this thread has never tracked a birth or death. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnThreadTermination(void* thread_data); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method should be called when a worker thread terminates, so that we 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can save all the thread data into a cache of reusable ThreadData instances. 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnThreadTerminationCleanup(); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleans up data structures, and returns statics to near pristine (mostly 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // uninitialized) state. If there is any chance that other threads are still 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // using the data structures, then the |leak| argument should be passed in as 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // true, and the data structures (birth maps, death maps, ThreadData 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // insntances, etc.) will be leaked and not deleted. If you have joined all 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads since the time that InitializeAndSetTrackingStatus() was called, 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then you can pass in a |leak| value of false, and this function will 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // delete recursively all data structures, starting with the list of 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ThreadData instances. 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void ShutdownSingleThreadedCleanup(bool leak); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When non-null, this specifies an external function that supplies monotone 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // increasing time functcion. 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static NowFunction* now_function_; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If true, now_function_ returns values that can be used to calculate queue 5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // time. 5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static bool now_function_is_time_; 5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use thread local store to identify which ThreadData to interact with. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::ThreadLocalStorage::StaticSlot tls_index_; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // List of ThreadData instances for use with worker threads. When a worker 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread is done (terminated), we push it onto this llist. When a new worker 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread is created, we first try to re-use a ThreadData instance from the 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list, and if none are available, construct a new one. 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is only accessed while list_lock_ is held. 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ThreadData* first_retired_worker_; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Link to the most recently created instance (starts a null terminated list). 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The list is traversed by about:profiler when it needs to snapshot data. 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is only accessed while list_lock_ is held. 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ThreadData* all_thread_data_list_head_; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The next available worker thread number. This should only be accessed when 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the list_lock_ is held. 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int worker_thread_data_creation_count_; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of times TLS has called us back to cleanup a ThreadData 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance. This is only accessed while list_lock_ is held. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int cleanup_count_; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Incarnation sequence number, indicating how many times (during unittests) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we've either transitioned out of UNINITIALIZED, or into that state. This 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value is only accessed while the list_lock_ is held. 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int incarnation_counter_; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Protection for access to all_thread_data_list_head_, and to 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unregistered_thread_data_pool_. This lock is leaked at shutdown. 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The lock is very infrequently used, so we can afford to just make a lazy 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instance and be safe. 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static base::LazyInstance<base::Lock>::Leaky list_lock_; 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We set status_ to SHUTDOWN when we shut down the tracking service. 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static Status status_; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Link to next instance (null terminated list). Used to globally track all 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // registered instances (corresponds to all registered threads where we keep 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data). 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadData* next_; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pointer to another ThreadData instance for a Worker-Thread that has been 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retired (its thread was terminated). This value is non-NULL only for a 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // retired ThreadData associated with a Worker-Thread. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadData* next_retired_worker_; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The name of the thread that is being recorded. If this thread has no 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message_loop, then this is a worker thread, with a sequence number postfix. 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string thread_name_; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicate if this is a worker thread, and the ThreadData contexts should be 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stored in the unregistered_thread_data_pool_ when not in use. 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Value is zero when it is not a worker thread. Value is a positive integer 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corresponding to the created thread name if it is a worker thread. 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int worker_thread_number_; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A map used on each thread to keep track of Births on this thread. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This map should only be accessed on the thread it was constructed on. 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When a snapshot is needed, this structure can be locked in place for the 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duration of the snapshotting activity. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthMap birth_map_; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Similar to birth_map_, this records informations about death of tracked 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instances (i.e., when a tracked instance was destroyed on this thread). 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is locked before changing, and hence other threads may access it by 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // locking before reading it. 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeathMap death_map_; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A set of parents that created children tasks on this thread. Each pair 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corresponds to potentially non-local Births (location and thread), and a 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // local Births (that took place on this thread). 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParentChildSet parent_child_set_; 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Lock to protect *some* access to BirthMap and DeathMap. The maps are 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // regularly read and written on this thread, but may only be read from other 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads. To support this, we acquire this lock if we are writing from this 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread, or reading from another thread. For reading from this thread we 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't need a lock, as there is no potential for a conflict since the 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // writing is only done from this thread. 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mutable base::Lock map_lock_; 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The stack of parents that are currently being profiled. This includes only 6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // tasks that have started a timer recently via PrepareForStartOfRun(), but 6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, 6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // but if a scoped region is profiled, or <sigh> a task runs a nested-message 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loop, then the stack can grow larger. Note that we don't try to deduct 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time in nested porfiles, as our current timer is based on wall-clock time, 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and not CPU time (and we're hopeful that nested timing won't be a 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // significant additional cost). 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParentStack parent_stack_; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A random number that we used to select decide which sample to keep as a 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // representative sample in each DeathData instance. We can't start off with 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // much randomness (because we can't call RandInt() on all our threads), so 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we stir in more and more as we go. 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 random_number_; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record of what the incarnation_counter_ was when this instance was created. 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the incarnation_counter_ has changed, then we avoid pushing into the 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pool (this is only critical in tests which go through multiple 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // incarnations). 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int incarnation_count_for_pool_; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Most recently started (i.e. most nested) stopwatch on the current thread, 6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // if it exists; NULL otherwise. 6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TaskStopwatch* current_stopwatch_; 6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ThreadData); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 7011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Stopwatch to measure task run time or simply create a time interval that will 7021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// be subtracted from the current most nested task's run time. Stopwatches 7031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// coordinate with the stopwatches in which they are nested to avoid 7041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// double-counting nested tasks run times. 7051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass BASE_EXPORT TaskStopwatch { 7071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 7081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Starts the stopwatch. 7091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TaskStopwatch(); 7101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ~TaskStopwatch(); 7111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Stops stopwatch. 7131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void Stop(); 7141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns the start time. 7161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TrackedTime StartTime() const; 7171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Task's duration is calculated as the wallclock duration between starting 7191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // and stopping this stopwatch, minus the wallclock durations of any other 7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // instances that are immediately nested in this one, started and stopped on 7211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // this thread during that period. 7221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32 RunDurationMs() const; 7231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Returns tracking info for the current thread. 7251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ThreadData* GetThreadData() const; 7261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci private: 7281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Time when the stopwatch was started. 7291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TrackedTime start_time_; 7301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Wallclock duration of the task. 7321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32 wallclock_duration_ms_; 7331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Tracking info for the current thread. 7351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ThreadData* current_thread_data_; 7361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Sum of wallclock durations of all stopwatches that were directly nested in 7381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // this one. 7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int32 excluded_duration_ms_; 7401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Stopwatch which was running on our thread when this stopwatch was started. 7421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // That preexisting stopwatch must be adjusted to the exclude the wallclock 7431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // duration of this stopwatch. 7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TaskStopwatch* parent_; 7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if DCHECK_IS_ON 7471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // State of the stopwatch. Stopwatch is first constructed in a running state, 7481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // then stopped, then destructed. 7491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci enum { 7501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci RUNNING, 7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci STOPPED 7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } state_; 7531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Currently running stopwatch that is directly nested in this one, if such 7551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // stopwatch exists. NULL otherwise. 7561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci TaskStopwatch* child_; 7571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 7581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 7591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 7601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//------------------------------------------------------------------------------ 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A snapshotted representation of a (parent, child) task pair, for tracking 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// hierarchical profiles. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT ParentChildPairSnapshot { 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParentChildPairSnapshot(); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit ParentChildPairSnapshot( 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ThreadData::ParentChildPair& parent_child); 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ParentChildPairSnapshot(); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshot parent; 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BirthOnThreadSnapshot child; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------ 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A snapshotted representation of the list of ThreadData objects for a process. 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct BASE_EXPORT ProcessDataSnapshot { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessDataSnapshot(); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ProcessDataSnapshot(); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TaskSnapshot> tasks; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<ParentChildPairSnapshot> descendants; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int process_id; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace tracked_objects 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // BASE_TRACKED_OBJECTS_H_ 791