| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_TRACKED_OBJECTS_H_ | 5 #ifndef BASE_TRACKED_OBJECTS_H_ |
| 6 #define BASE_TRACKED_OBJECTS_H_ | 6 #define BASE_TRACKED_OBJECTS_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <map> | 9 #include <map> |
| 10 #include <stack> | 10 #include <stack> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base_export.h" | 14 #include "base/base_export.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/profiler/tracked_time.h" | 16 #include "base/profiler/tracked_time.h" |
| 17 #include "base/time.h" | 17 #include "base/time.h" |
| 18 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
| 19 #include "base/threading/thread_local_storage.h" | 19 #include "base/threading/thread_local_storage.h" |
| 20 #include "base/tracking_info.h" | 20 #include "base/tracking_info.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 | 22 |
| 23 // TrackedObjects provides a database of stats about objects (generally Tasks) | 23 // TrackedObjects provides a database of stats about objects (generally Tasks) |
| 24 // that are tracked. Tracking means their birth, death, duration, birth thread, | 24 // that are tracked. Tracking means their birth, death, duration, birth thread, |
| 25 // death thread, and birth place are recorded. This data is carefully spread | 25 // death thread, and birth place are recorded. This data is carefully spread |
| 26 // across a series of objects so that the counts and times can be rapidly | 26 // across a series of objects so that the counts and times can be rapidly |
| 27 // updated without (usually) having to lock the data, and hence there is usually | 27 // updated without (usually) having to lock the data, and hence there is usually |
| 28 // very little contention caused by the tracking. The data can be viewed via | 28 // very little contention caused by the tracking. The data can be viewed via |
| 29 // the about:tracking URL, with a variety of sorting and filtering choices. | 29 // the about:profiler URL, with a variety of sorting and filtering choices. |
| 30 // | 30 // |
| 31 // These classes serve as the basis of a profiler of sorts for the Tasks system. | 31 // These classes serve as the basis of a profiler of sorts for the Tasks system. |
| 32 // As a result, design decisions were made to maximize speed, by minimizing | 32 // As a result, design decisions were made to maximize speed, by minimizing |
| 33 // recurring allocation/deallocation, lock contention and data copying. In the | 33 // recurring allocation/deallocation, lock contention and data copying. In the |
| 34 // "stable" state, which is reached relatively quickly, there is no separate | 34 // "stable" state, which is reached relatively quickly, there is no separate |
| 35 // marginal allocation cost associated with construction or destruction of | 35 // marginal allocation cost associated with construction or destruction of |
| 36 // tracked objects, no locks are generally employed, and probably the largest | 36 // tracked objects, no locks are generally employed, and probably the largest |
| 37 // computational cost is associated with obtaining start and stop times for | 37 // computational cost is associated with obtaining start and stop times for |
| 38 // instances as they are created and destroyed. | 38 // instances as they are created and destroyed. |
| 39 // | 39 // |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 // requires the use of the list_lock_. | 111 // requires the use of the list_lock_. |
| 112 // When new ThreadData instances is added to the global list, it is pre-pended, | 112 // When new ThreadData instances is added to the global list, it is pre-pended, |
| 113 // which ensures that any prior acquisition of the list is valid (i.e., the | 113 // which ensures that any prior acquisition of the list is valid (i.e., the |
| 114 // holder can iterate over it without fear of it changing, or the necessity of | 114 // holder can iterate over it without fear of it changing, or the necessity of |
| 115 // using an additional lock. Iterations are actually pretty rare (used | 115 // using an additional lock. Iterations are actually pretty rare (used |
| 116 // primarilly for cleanup, or snapshotting data for display), so this lock has | 116 // primarilly for cleanup, or snapshotting data for display), so this lock has |
| 117 // very little global performance impact. | 117 // very little global performance impact. |
| 118 // | 118 // |
| 119 // The above description tries to define the high performance (run time) | 119 // The above description tries to define the high performance (run time) |
| 120 // portions of these classes. After gathering statistics, calls instigated | 120 // portions of these classes. After gathering statistics, calls instigated |
| 121 // by visiting about:tracking will assemble and aggregate data for display. The | 121 // by visiting about:profiler will assemble and aggregate data for display. The |
| 122 // following data structures are used for producing such displays. They are | 122 // following data structures are used for producing such displays. They are |
| 123 // not performance critical, and their only major constraint is that they should | 123 // not performance critical, and their only major constraint is that they should |
| 124 // be able to run concurrently with ongoing augmentation of the birth and death | 124 // be able to run concurrently with ongoing augmentation of the birth and death |
| 125 // data. | 125 // data. |
| 126 // | 126 // |
| 127 // For a given birth location, information about births is spread across data | 127 // For a given birth location, information about births is spread across data |
| 128 // structures that are asynchronously changing on various threads. For display | 128 // structures that are asynchronously changing on various threads. For display |
| 129 // purposes, we need to construct Snapshot instances for each combination of | 129 // purposes, we need to construct Snapshot instances for each combination of |
| 130 // birth thread, death thread, and location, along with the count of such | 130 // birth thread, death thread, and location, along with the count of such |
| 131 // lifetimes. We gather such data into a Snapshot instances, so that such | 131 // lifetimes. We gather such data into a Snapshot instances, so that such |
| (...skipping 14 matching lines...) Expand all Loading... |
| 146 // of a bad memory reference). | 146 // of a bad memory reference). |
| 147 // | 147 // |
| 148 // After an array of Snapshots instances are collected into a DataCollector, | 148 // After an array of Snapshots instances are collected into a DataCollector, |
| 149 // they need to be prepared for displaying our output. We currently implement a | 149 // they need to be prepared for displaying our output. We currently implement a |
| 150 // direct rendering to HTML, but we will soon have a JSON serialization as well. | 150 // direct rendering to HTML, but we will soon have a JSON serialization as well. |
| 151 | 151 |
| 152 // For direct HTML display, the data must be sorted, and possibly aggregated | 152 // For direct HTML display, the data must be sorted, and possibly aggregated |
| 153 // (example: how many threads are in a specific consecutive set of Snapshots? | 153 // (example: how many threads are in a specific consecutive set of Snapshots? |
| 154 // What was the total birth count for that set? etc.). Aggregation instances | 154 // What was the total birth count for that set? etc.). Aggregation instances |
| 155 // collect running sums of any set of snapshot instances, and are used to print | 155 // collect running sums of any set of snapshot instances, and are used to print |
| 156 // sub-totals in an about:tracking page. | 156 // sub-totals in an about:profiler page. |
| 157 // | 157 // |
| 158 // TODO(jar): I need to store DataCollections, and provide facilities for taking | 158 // TODO(jar): I need to store DataCollections, and provide facilities for taking |
| 159 // the difference between two gathered DataCollections. For now, I'm just | 159 // the difference between two gathered DataCollections. For now, I'm just |
| 160 // adding a hack that Reset()s to zero all counts and stats. This is also | 160 // adding a hack that Reset()s to zero all counts and stats. This is also |
| 161 // done in a slighly thread-unsafe fashion, as the resetting is done | 161 // done in a slighly thread-unsafe fashion, as the resetting is done |
| 162 // asynchronously relative to ongoing updates (but all data is 32 bit in size). | 162 // asynchronously relative to ongoing updates (but all data is 32 bit in size). |
| 163 // For basic profiling, this will work "most of the time," and should be | 163 // For basic profiling, this will work "most of the time," and should be |
| 164 // sufficient... but storing away DataCollections is the "right way" to do this. | 164 // sufficient... but storing away DataCollections is the "right way" to do this. |
| 165 // We'll accomplish this via JavaScript storage of snapshots, and then we'll | 165 // We'll accomplish this via JavaScript storage of snapshots, and then we'll |
| 166 // remove the Reset() methods. | 166 // remove the Reset() methods. |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 // Initializes all statics if needed (this initialization call should be made | 656 // Initializes all statics if needed (this initialization call should be made |
| 657 // while we are single threaded). Returns false if unable to initialize. | 657 // while we are single threaded). Returns false if unable to initialize. |
| 658 static bool Initialize(); | 658 static bool Initialize(); |
| 659 | 659 |
| 660 // Sets internal status_ to either become ACTIVE, or DEACTIVATED, | 660 // Sets internal status_ to either become ACTIVE, or DEACTIVATED, |
| 661 // based on argument being true or false respectively. | 661 // based on argument being true or false respectively. |
| 662 // If tracking is not compiled in, this function will return false. | 662 // If tracking is not compiled in, this function will return false. |
| 663 static bool InitializeAndSetTrackingStatus(bool status); | 663 static bool InitializeAndSetTrackingStatus(bool status); |
| 664 static bool tracking_status(); | 664 static bool tracking_status(); |
| 665 | 665 |
| 666 // Special versions of Now() for getting times at start and end of a tracked |
| 667 // run. They are super fast when tracking is disabled, and have some internal |
| 668 // side effects when we are tracking, so that we can deduce the amount of time |
| 669 // accumulated outside of execution of tracked runs. |
| 670 static TrackedTime NowForStartOfRun(); |
| 671 static TrackedTime NowForEndOfRun(); |
| 672 |
| 666 // Provide a time function that does nothing (runs fast) when we don't have | 673 // Provide a time function that does nothing (runs fast) when we don't have |
| 667 // the profiler enabled. It will generally be optimized away when it is | 674 // the profiler enabled. It will generally be optimized away when it is |
| 668 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of | 675 // ifdef'ed to be small enough (allowing the profiler to be "compiled out" of |
| 669 // the code). | 676 // the code). |
| 670 static TrackedTime Now(); | 677 static TrackedTime Now(); |
| 671 | 678 |
| 672 private: | 679 private: |
| 673 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it | 680 // Allow only tests to call ShutdownSingleThreadedCleanup. We NEVER call it |
| 674 // in production code. | 681 // in production code. |
| 675 friend class TrackedObjectsTest; | 682 friend class TrackedObjectsTest; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 // threads since the time that InitializeAndSetTrackingStatus() was called, | 722 // threads since the time that InitializeAndSetTrackingStatus() was called, |
| 716 // then you can pass in a |leak| value of false, and this function will | 723 // then you can pass in a |leak| value of false, and this function will |
| 717 // delete recursively all data structures, starting with the list of | 724 // delete recursively all data structures, starting with the list of |
| 718 // ThreadData instances. | 725 // ThreadData instances. |
| 719 static void ShutdownSingleThreadedCleanup(bool leak); | 726 static void ShutdownSingleThreadedCleanup(bool leak); |
| 720 | 727 |
| 721 // We use thread local store to identify which ThreadData to interact with. | 728 // We use thread local store to identify which ThreadData to interact with. |
| 722 static base::ThreadLocalStorage::Slot tls_index_; | 729 static base::ThreadLocalStorage::Slot tls_index_; |
| 723 | 730 |
| 724 // Link to the most recently created instance (starts a null terminated list). | 731 // Link to the most recently created instance (starts a null terminated list). |
| 725 // The list is traversed by about:tracking when it needs to snapshot data. | 732 // The list is traversed by about:profiler when it needs to snapshot data. |
| 726 // This is only accessed while list_lock_ is held. | 733 // This is only accessed while list_lock_ is held. |
| 727 static ThreadData* all_thread_data_list_head_; | 734 static ThreadData* all_thread_data_list_head_; |
| 728 // Set of ThreadData instances for use with worker threads. When a worker | 735 // Set of ThreadData instances for use with worker threads. When a worker |
| 729 // thread is done (terminating), we push it into this pool. When a new worker | 736 // thread is done (terminating), we push it into this pool. When a new worker |
| 730 // thread is created, we first try to re-use a ThreadData instance from the | 737 // thread is created, we first try to re-use a ThreadData instance from the |
| 731 // pool, and if none are available, construct a new one. | 738 // pool, and if none are available, construct a new one. |
| 732 // This is only accessed while list_lock_ is held. | 739 // This is only accessed while list_lock_ is held. |
| 733 static ThreadDataPool* unregistered_thread_data_pool_; | 740 static ThreadDataPool* unregistered_thread_data_pool_; |
| 734 // The next available thread number. This should only be accessed when the | 741 // The next available thread number. This should only be accessed when the |
| 735 // list_lock_ is held. | 742 // list_lock_ is held. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 } | 814 } |
| 808 | 815 |
| 809 private: | 816 private: |
| 810 | 817 |
| 811 DISALLOW_COPY_AND_ASSIGN(AutoTracking); | 818 DISALLOW_COPY_AND_ASSIGN(AutoTracking); |
| 812 }; | 819 }; |
| 813 | 820 |
| 814 } // namespace tracked_objects | 821 } // namespace tracked_objects |
| 815 | 822 |
| 816 #endif // BASE_TRACKED_OBJECTS_H_ | 823 #endif // BASE_TRACKED_OBJECTS_H_ |
| OLD | NEW |