Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 // Activity tracking provides a low-overhead method of collecting information | 5 // Activity tracking provides a low-overhead method of collecting information |
| 6 // about the state of the application for analysis both while it is running | 6 // about the state of the application for analysis both while it is running |
| 7 // and after it has terminated unexpectedly. Its primary purpose is to help | 7 // and after it has terminated unexpectedly. Its primary purpose is to help |
| 8 // locate reasons the browser becomes unresponsive by providing insight into | 8 // locate reasons the browser becomes unresponsive by providing insight into |
| 9 // what all the various threads and processes are (or were) doing. | 9 // what all the various threads and processes are (or were) doing. |
| 10 | 10 |
| 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ | 11 #ifndef BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ | 12 #define BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| 13 | 13 |
| 14 // std::atomic is undesired due to performance issues when used as global | 14 // std::atomic is undesired due to performance issues when used as global |
| 15 // variables. There are no such instances here. This module uses the | 15 // variables. There are no such instances here. This module uses the |
| 16 // PersistentMemoryAllocator which also uses std::atomic and is written | 16 // PersistentMemoryAllocator which also uses std::atomic and is written |
| 17 // by the same author. | 17 // by the same author. |
| 18 #include <atomic> | 18 #include <atomic> |
| 19 #include <map> | 19 #include <map> |
| 20 #include <memory> | 20 #include <memory> |
| 21 #include <string> | 21 #include <string> |
| 22 #include <vector> | 22 #include <vector> |
| 23 | 23 |
| 24 #include "base/base_export.h" | 24 #include "base/base_export.h" |
| 25 #include "base/compiler_specific.h" | 25 #include "base/compiler_specific.h" |
| 26 #include "base/gtest_prod_util.h" | 26 #include "base/gtest_prod_util.h" |
| 27 #include "base/location.h" | 27 #include "base/location.h" |
| 28 #include "base/metrics/persistent_memory_allocator.h" | 28 #include "base/metrics/persistent_memory_allocator.h" |
| 29 #include "base/strings/string_piece.h" | |
| 29 #include "base/strings/utf_string_conversions.h" | 30 #include "base/strings/utf_string_conversions.h" |
| 30 #include "base/threading/platform_thread.h" | 31 #include "base/threading/platform_thread.h" |
| 31 #include "base/threading/thread_checker.h" | 32 #include "base/threading/thread_checker.h" |
| 32 #include "base/threading/thread_local_storage.h" | 33 #include "base/threading/thread_local_storage.h" |
| 33 | 34 |
| 34 namespace base { | 35 namespace base { |
| 35 | 36 |
| 36 struct PendingTask; | 37 struct PendingTask; |
| 37 | 38 |
| 38 class FilePath; | 39 class FilePath; |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 | 334 |
| 334 ValueType type_; | 335 ValueType type_; |
| 335 uint64_t short_value_; // Used to hold copy of numbers, etc. | 336 uint64_t short_value_; // Used to hold copy of numbers, etc. |
| 336 std::string long_value_; // Used to hold copy of raw/string data. | 337 std::string long_value_; // Used to hold copy of raw/string data. |
| 337 StringPiece ref_value_; // Used to hold reference to external data. | 338 StringPiece ref_value_; // Used to hold reference to external data. |
| 338 }; | 339 }; |
| 339 | 340 |
| 340 using Snapshot = std::map<std::string, TypedValue>; | 341 using Snapshot = std::map<std::string, TypedValue>; |
| 341 | 342 |
| 342 ActivityUserData(void* memory, size_t size); | 343 ActivityUserData(void* memory, size_t size); |
| 343 ~ActivityUserData(); | 344 virtual ~ActivityUserData(); |
| 344 | 345 |
| 345 // Gets the unique ID number for this user data. If this changes then the | 346 // Gets the unique ID number for this user data. If this changes then the |
| 346 // contents have been overwritten by another thread. The return value is | 347 // contents have been overwritten by another thread. The return value is |
| 347 // always non-zero unless it's actually just a data "sink". | 348 // always non-zero unless it's actually just a data "sink". |
| 348 uint32_t id() const { | 349 uint32_t id() const { |
| 349 return memory_ ? id_->load(std::memory_order_relaxed) : 0; | 350 return memory_ ? id_->load(std::memory_order_relaxed) : 0; |
| 350 } | 351 } |
| 351 | 352 |
| 352 // Writes a |value| (as part of a key/value pair) that will be included with | 353 // Writes a |value| (as part of a key/value pair) that will be included with |
| 353 // the activity in any reports. The same |name| can be written multiple times | 354 // the activity in any reports. The same |name| can be written multiple times |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 395 // Creates a snapshot of the key/value pairs contained within. The returned | 396 // Creates a snapshot of the key/value pairs contained within. The returned |
| 396 // data will be fixed, independent of whatever changes afterward. There is | 397 // data will be fixed, independent of whatever changes afterward. There is |
| 397 // protection against concurrent modification of the values but no protection | 398 // protection against concurrent modification of the values but no protection |
| 398 // against a complete overwrite of the contents; the caller must ensure that | 399 // against a complete overwrite of the contents; the caller must ensure that |
| 399 // the memory segment is not going to be re-initialized while this runs. | 400 // the memory segment is not going to be re-initialized while this runs. |
| 400 bool CreateSnapshot(Snapshot* output_snapshot) const; | 401 bool CreateSnapshot(Snapshot* output_snapshot) const; |
| 401 | 402 |
| 402 // Gets the base memory address used for storing data. | 403 // Gets the base memory address used for storing data. |
| 403 const void* GetBaseAddress(); | 404 const void* GetBaseAddress(); |
| 404 | 405 |
| 406 protected: | |
| 407 virtual void Set(StringPiece name, | |
| 408 ValueType type, | |
| 409 const void* memory, | |
| 410 size_t size); | |
| 411 | |
| 405 private: | 412 private: |
| 406 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); | 413 FRIEND_TEST_ALL_PREFIXES(ActivityTrackerTest, UserDataTest); |
| 407 | 414 |
| 408 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; | 415 enum : size_t { kMemoryAlignment = sizeof(uint64_t) }; |
| 409 | 416 |
| 410 // A structure used to reference data held outside of persistent memory. | 417 // A structure used to reference data held outside of persistent memory. |
| 411 struct ReferenceRecord { | 418 struct ReferenceRecord { |
| 412 uint64_t address; | 419 uint64_t address; |
| 413 uint64_t size; | 420 uint64_t size; |
| 414 }; | 421 }; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 428 ValueInfo(ValueInfo&&); | 435 ValueInfo(ValueInfo&&); |
| 429 ~ValueInfo(); | 436 ~ValueInfo(); |
| 430 | 437 |
| 431 StringPiece name; // The "key" of the record. | 438 StringPiece name; // The "key" of the record. |
| 432 ValueType type; // The type of the value. | 439 ValueType type; // The type of the value. |
| 433 void* memory; // Where the "value" is held. | 440 void* memory; // Where the "value" is held. |
| 434 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. | 441 std::atomic<uint16_t>* size_ptr; // Address of the actual size of value. |
| 435 size_t extent; // The total storage of the value, | 442 size_t extent; // The total storage of the value, |
| 436 }; // typically rounded up for alignment. | 443 }; // typically rounded up for alignment. |
| 437 | 444 |
| 438 void Set(StringPiece name, ValueType type, const void* memory, size_t size); | |
| 439 void SetReference(StringPiece name, | 445 void SetReference(StringPiece name, |
| 440 ValueType type, | 446 ValueType type, |
| 441 const void* memory, | 447 const void* memory, |
| 442 size_t size); | 448 size_t size); |
| 443 | 449 |
| 444 // Loads any data already in the memory segment. This allows for accessing | 450 // Loads any data already in the memory segment. This allows for accessing |
| 445 // records created previously. | 451 // records created previously. |
| 446 void ImportExistingData() const; | 452 void ImportExistingData() const; |
| 447 | 453 |
| 448 // A map of all the values within the memory block, keyed by name for quick | 454 // A map of all the values within the memory block, keyed by name for quick |
| 449 // updates of the values. This is "mutable" because it changes on "const" | 455 // updates of the values. This is "mutable" because it changes on "const" |
| 450 // objects even when the actual data values can't change. | 456 // objects even when the actual data values can't change. |
| 451 mutable std::map<StringPiece, ValueInfo> values_; | 457 mutable std::map<StringPiece, ValueInfo> values_; |
| 452 | 458 |
| 453 // Information about the memory block in which new data can be stored. These | 459 // Information about the memory block in which new data can be stored. These |
| 454 // are "mutable" because they change even on "const" objects that are just | 460 // are "mutable" because they change even on "const" objects that are just |
| 455 // skipping already set values. | 461 // skipping already set values. |
| 456 mutable char* memory_; | 462 mutable char* memory_; |
| 457 mutable size_t available_; | 463 mutable size_t available_; |
| 458 | 464 |
| 459 // A pointer to the unique ID for this instance. | 465 // A pointer to the unique ID for this instance. |
| 460 std::atomic<uint32_t>* const id_; | 466 std::atomic<uint32_t>* const id_; |
| 461 | 467 |
| 462 base::ThreadChecker thread_checker_; | |
| 463 | |
| 464 // This ID is used to create unique indentifiers for user data so that it's | 468 // This ID is used to create unique indentifiers for user data so that it's |
| 465 // possible to tell if the information has been overwritten. | 469 // possible to tell if the information has been overwritten. |
| 466 static std::atomic<uint32_t> next_id_; | 470 static std::atomic<uint32_t> next_id_; |
| 467 | 471 |
| 468 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); | 472 DISALLOW_COPY_AND_ASSIGN(ActivityUserData); |
| 469 }; | 473 }; |
| 470 | 474 |
| 471 // This class manages tracking a stack of activities for a single thread in | 475 // This class manages tracking a stack of activities for a single thread in |
| 472 // a persistent manner, implementing a bounded-size stack in a fixed-size | 476 // a persistent manner, implementing a bounded-size stack in a fixed-size |
| 473 // memory allocation. In order to support an operational mode where another | 477 // memory allocation. In order to support an operational mode where another |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 773 | 777 |
| 774 // Records a log message. The current implementation does NOT recycle these | 778 // Records a log message. The current implementation does NOT recycle these |
| 775 // only store critical messages such as FATAL ones. | 779 // only store critical messages such as FATAL ones. |
| 776 void RecordLogMessage(StringPiece message); | 780 void RecordLogMessage(StringPiece message); |
| 777 | 781 |
| 778 // Records a module load/unload event. This is safe to call multiple times | 782 // Records a module load/unload event. This is safe to call multiple times |
| 779 // even with the same information. | 783 // even with the same information. |
| 780 void RecordModuleInfo(const ModuleInfo& info); | 784 void RecordModuleInfo(const ModuleInfo& info); |
| 781 | 785 |
| 782 // Accesses the global data record for storing arbitrary key/value pairs. | 786 // Accesses the global data record for storing arbitrary key/value pairs. |
| 783 ActivityUserData& user_data() { return user_data_; } | 787 ActivityUserData& global_data() { return global_data_; } |
| 788 | |
| 789 // Record field trial information. This will work even before a global | |
| 790 // tracker has been created, holding that information internally until a | |
| 791 // global tracker is created at which point everything collected will be | |
| 792 // dumped into it. | |
| 793 static void RecordFieldTrial(const std::string& trial_name, | |
| 794 StringPiece group_name); | |
| 795 | |
| 796 // Disable all filed trial recording. This should be called when its known | |
| 797 // that no global tracker will be created so as to not hold field-trial | |
| 798 // information that will never be collected. | |
| 799 static void DisableFieldTrialRecording(); | |
| 784 | 800 |
| 785 private: | 801 private: |
| 786 friend class GlobalActivityAnalyzer; | 802 friend class GlobalActivityAnalyzer; |
| 787 friend class ScopedThreadActivity; | 803 friend class ScopedThreadActivity; |
| 788 friend class ActivityTrackerTest; | 804 friend class ActivityTrackerTest; |
| 789 | 805 |
| 790 enum : int { | 806 enum : int { |
| 791 // The maximum number of threads that can be tracked within a process. If | 807 // The maximum number of threads that can be tracked within a process. If |
| 792 // more than this number run concurrently, tracking of new ones may cease. | 808 // more than this number run concurrently, tracking of new ones may cease. |
| 793 kMaxThreadCount = 100, | 809 kMaxThreadCount = 100, |
| 794 kCachedThreadMemories = 10, | 810 kCachedThreadMemories = 10, |
| 795 kCachedUserDataMemories = 10, | 811 kCachedUserDataMemories = 10, |
| 796 }; | 812 }; |
| 797 | 813 |
| 814 // A wrapper around ActivityUserData that is thread-safe and thus can be used | |
| 815 // in the global scope without the requirement of being called from only one | |
| 816 // thread. | |
| 817 class GlobalUserData : public ActivityUserData { | |
| 818 public: | |
| 819 GlobalUserData(void* memory, size_t size); | |
| 820 ~GlobalUserData() override; | |
| 821 | |
| 822 private: | |
| 823 void Set(StringPiece name, | |
| 824 ValueType type, | |
| 825 const void* memory, | |
| 826 size_t size) override; | |
| 827 | |
| 828 Lock data_lock_; | |
| 829 | |
| 830 DISALLOW_COPY_AND_ASSIGN(GlobalUserData); | |
| 831 }; | |
| 832 | |
| 798 // State of a module as stored in persistent memory. This supports a single | 833 // State of a module as stored in persistent memory. This supports a single |
| 799 // loading of a module only. If modules are loaded multiple times at | 834 // loading of a module only. If modules are loaded multiple times at |
| 800 // different addresses, only the last will be recorded and an unload will | 835 // different addresses, only the last will be recorded and an unload will |
| 801 // not revert to the information of any other addresses. | 836 // not revert to the information of any other addresses. |
| 802 struct BASE_EXPORT ModuleInfoRecord { | 837 struct BASE_EXPORT ModuleInfoRecord { |
| 803 // SHA1(ModuleInfoRecord): Increment this if structure changes! | 838 // SHA1(ModuleInfoRecord): Increment this if structure changes! |
| 804 static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; | 839 static constexpr uint32_t kPersistentTypeId = 0x05DB5F41 + 1; |
| 805 | 840 |
| 806 // Expected size for 32/64-bit check by PersistentMemoryAllocator. | 841 // Expected size for 32/64-bit check by PersistentMemoryAllocator. |
| 807 static constexpr size_t kExpectedInstanceSize = 56; | 842 static constexpr size_t kExpectedInstanceSize = 56; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 892 // A caching memory allocator for thread-tracker objects. | 927 // A caching memory allocator for thread-tracker objects. |
| 893 ActivityTrackerMemoryAllocator thread_tracker_allocator_; | 928 ActivityTrackerMemoryAllocator thread_tracker_allocator_; |
| 894 base::Lock thread_tracker_allocator_lock_; | 929 base::Lock thread_tracker_allocator_lock_; |
| 895 | 930 |
| 896 // A caching memory allocator for user data attached to activity data. | 931 // A caching memory allocator for user data attached to activity data. |
| 897 ActivityTrackerMemoryAllocator user_data_allocator_; | 932 ActivityTrackerMemoryAllocator user_data_allocator_; |
| 898 base::Lock user_data_allocator_lock_; | 933 base::Lock user_data_allocator_lock_; |
| 899 | 934 |
| 900 // An object for holding global arbitrary key value pairs. Values must always | 935 // An object for holding global arbitrary key value pairs. Values must always |
| 901 // be written from the main UI thread. | 936 // be written from the main UI thread. |
| 902 ActivityUserData user_data_; | 937 ActivityUserData global_data_; |
|
manzagop (departed)
2017/02/03 19:01:49
Do you mean for this to be of type GlobalUserData?
bcwhite
2017/02/03 19:07:04
Oops! Yes!
| |
| 903 | 938 |
| 904 // A map of global module information, keyed by module path. | 939 // A map of global module information, keyed by module path. |
| 905 std::map<const std::string, ModuleInfoRecord*> modules_; | 940 std::map<const std::string, ModuleInfoRecord*> modules_; |
| 906 base::Lock modules_lock_; | 941 base::Lock modules_lock_; |
| 907 | 942 |
| 908 // The active global activity tracker. | 943 // The active global activity tracker. |
| 909 static GlobalActivityTracker* g_tracker_; | 944 static GlobalActivityTracker* g_tracker_; |
| 910 | 945 |
| 911 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); | 946 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); |
| 912 }; | 947 }; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 ScopedProcessWaitActivity(const void* program_counter, | 1070 ScopedProcessWaitActivity(const void* program_counter, |
| 1036 const base::Process* process); | 1071 const base::Process* process); |
| 1037 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); | 1072 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); |
| 1038 }; | 1073 }; |
| 1039 #endif | 1074 #endif |
| 1040 | 1075 |
| 1041 } // namespace debug | 1076 } // namespace debug |
| 1042 } // namespace base | 1077 } // namespace base |
| 1043 | 1078 |
| 1044 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ | 1079 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ |
| OLD | NEW |