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

Side by Side Diff: base/debug/activity_tracker.h

Issue 2666653002: Record field-trial information in stability file for crash analysis. (Closed)
Patch Set: addressed review comments by asvitkine Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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. This call is completely thread-safe.
Alexei Svitkine (slow) 2017/02/07 16:14:06 Nit: Remove the word "completely". "thread safe" i
bcwhite 2017/02/07 17:39:30 Done.
793 static void RecordFieldTrial(const std::string& trial_name,
794 const std::string& group_name);
795
796 // Disable all filed trial recording. This should be called when its known
Alexei Svitkine (slow) 2017/02/07 16:14:06 field
bcwhite 2017/02/07 17:39:30 Done.
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
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 GlobalUserData global_data_;
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
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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698