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

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

Issue 2387733002: Move memory management code into separate class for future reuse. (Closed)
Patch Set: added comment and tests Created 4 years, 2 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
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 static ActivityData ForProcess(const int64_t id) { 118 static ActivityData ForProcess(const int64_t id) {
119 ActivityData data; 119 ActivityData data;
120 data.process.process_id = id; 120 data.process.process_id = id;
121 return data; 121 return data;
122 } 122 }
123 }; 123 };
124 124
125 // A "null" activity-data that can be passed to indicate "do not change". 125 // A "null" activity-data that can be passed to indicate "do not change".
126 extern const ActivityData kNullActivityData; 126 extern const ActivityData kNullActivityData;
127 127
128
129 // A helper class that is used for managing memory allocations within a
130 // persistent memory allocator. Instances of this class are NOT thread-safe.
131 // Use from a single thread or protect access with a lock.
132 class ActivityTrackerMemoryAllocator {
133 public:
134 using Reference = PersistentMemoryAllocator::Reference;
135
136 // Creates a instance for allocating objects of a fixed |object_type| and
137 // |object_size|. An internal cache of the last |cache_size| released
138 // references will be kept for quick future fetches.
139 ActivityTrackerMemoryAllocator(PersistentMemoryAllocator* allocator,
140 uint32_t object_type,
141 size_t object_size,
142 size_t cache_size);
143 ~ActivityTrackerMemoryAllocator();
144
145 // Gets a reference to an object of the configured type. This can return
146 // a null reference if it was not possible to allocate the memory.
147 Reference GetObjectReference();
148
149 // Returns an object to the "free" pool.
150 void ReleaseObjectReference(Reference ref);
151
152 // The current "used size" of the internal cache, visible for testing.
153 size_t cache_used() { return cache_used_; }
Alexei Svitkine (slow) 2016/10/13 15:25:21 Nit: const
bcwhite 2016/10/13 17:03:22 Done.
154
155 private:
156 PersistentMemoryAllocator* const allocator_;
157 const uint32_t object_type_;
158 const size_t object_size_;
159 const size_t cache_size_;
160
161 // An iterator for going through persistent memory looking for free'd objects.
162 PersistentMemoryAllocator::Iterator iterator_;
163
164 // The cache of released object memories.
165 std::unique_ptr<Reference[]> cache_values_;
166 size_t cache_used_;
167
168 DISALLOW_COPY_AND_ASSIGN(ActivityTrackerMemoryAllocator);
169 };
170
171
128 // This structure is the full contents recorded for every activity pushed 172 // This structure is the full contents recorded for every activity pushed
129 // onto the stack. The |activity_type| indicates what is actually stored in 173 // onto the stack. The |activity_type| indicates what is actually stored in
130 // the |data| field. All fields must be explicitly sized types to ensure no 174 // the |data| field. All fields must be explicitly sized types to ensure no
131 // interoperability problems between 32-bit and 64-bit systems. 175 // interoperability problems between 32-bit and 64-bit systems.
132 struct Activity { 176 struct Activity {
133 // The type of an activity on the stack. Activities are broken into 177 // The type of an activity on the stack. Activities are broken into
134 // categories with the category ID taking the top 4 bits and the lower 178 // categories with the category ID taking the top 4 bits and the lower
135 // bits representing an action within that category. This combination 179 // bits representing an action within that category. This combination
136 // makes it easy to "switch" based on the type during analysis. 180 // makes it easy to "switch" based on the type during analysis.
137 enum Type : uint8_t { 181 enum Type : uint8_t {
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 base::ThreadChecker thread_checker_; 381 base::ThreadChecker thread_checker_;
338 382
339 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker); 383 DISALLOW_COPY_AND_ASSIGN(ThreadActivityTracker);
340 }; 384 };
341 385
342 386
343 // The global tracker manages all the individual thread trackers. Memory for 387 // The global tracker manages all the individual thread trackers. Memory for
344 // the thread trackers is taken from a PersistentMemoryAllocator which allows 388 // the thread trackers is taken from a PersistentMemoryAllocator which allows
345 // for the data to be analyzed by a parallel process or even post-mortem. 389 // for the data to be analyzed by a parallel process or even post-mortem.
346 class BASE_EXPORT GlobalActivityTracker { 390 class BASE_EXPORT GlobalActivityTracker {
347 template <typename T>
348 class ThreadSafeStack {
349 public:
350 ThreadSafeStack(size_t size)
351 : size_(size), values_(new T[size]), used_(0) {}
352 ~ThreadSafeStack() {}
353
354 size_t size() { return size_; }
355 size_t used() {
356 base::AutoLock autolock(lock_);
357 return used_;
358 }
359
360 bool push(T value) {
361 base::AutoLock autolock(lock_);
362 if (used_ == size_)
363 return false;
364 values_[used_++] = value;
365 return true;
366 }
367
368 bool pop(T* out_value) {
369 base::AutoLock autolock(lock_);
370 if (used_ == 0)
371 return false;
372 *out_value = values_[--used_];
373 return true;
374 }
375
376 private:
377 const size_t size_;
378
379 std::unique_ptr<T[]> values_;
380 size_t used_;
381 base::Lock lock_;
382
383 private:
384 DISALLOW_COPY_AND_ASSIGN(ThreadSafeStack);
385 };
386
387 public: 391 public:
388 // Type identifiers used when storing in persistent memory so they can be 392 // Type identifiers used when storing in persistent memory so they can be
389 // identified during extraction; the first 4 bytes of the SHA1 of the name 393 // identified during extraction; the first 4 bytes of the SHA1 of the name
390 // is used as a unique integer. A "version number" is added to the base 394 // is used as a unique integer. A "version number" is added to the base
391 // so that, if the structure of that object changes, stored older versions 395 // so that, if the structure of that object changes, stored older versions
392 // will be safely ignored. These are public so that an external process 396 // will be safely ignored. These are public so that an external process
393 // can recognize records of this type within an allocator. 397 // can recognize records of this type within an allocator.
394 enum : uint32_t { 398 enum : uint32_t {
395 kTypeIdActivityTracker = 0x5D7381AF + 1, // SHA1(ActivityTracker) v1 399 kTypeIdActivityTracker = 0x5D7381AF + 1, // SHA1(ActivityTracker) v1
396 kTypeIdActivityTrackerFree = 0x3F0272FB + 1, // SHA1(ActivityTrackerFree)
397 }; 400 };
398 401
399 // This is a thin wrapper around the thread-tracker's ScopedActivity that 402 // This is a thin wrapper around the thread-tracker's ScopedActivity that
400 // accesses the global tracker to provide some of the information, notably 403 // accesses the global tracker to provide some of the information, notably
401 // which thread-tracker to use. It is safe to create even if activity 404 // which thread-tracker to use. It is safe to create even if activity
402 // tracking is not enabled. 405 // tracking is not enabled.
403 class BASE_EXPORT ScopedThreadActivity 406 class BASE_EXPORT ScopedThreadActivity
404 : public ThreadActivityTracker::ScopedActivity { 407 : public ThreadActivityTracker::ScopedActivity {
405 public: 408 public:
406 ScopedThreadActivity(const void* origin, 409 ScopedThreadActivity(const void* origin,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 // Releases the activity-tracker for the current thread (for testing only). 495 // Releases the activity-tracker for the current thread (for testing only).
493 void ReleaseTrackerForCurrentThreadForTesting(); 496 void ReleaseTrackerForCurrentThreadForTesting();
494 497
495 private: 498 private:
496 friend class ActivityTrackerTest; 499 friend class ActivityTrackerTest;
497 500
498 enum : int { 501 enum : int {
499 // The maximum number of threads that can be tracked within a process. If 502 // The maximum number of threads that can be tracked within a process. If
500 // more than this number run concurrently, tracking of new ones may cease. 503 // more than this number run concurrently, tracking of new ones may cease.
501 kMaxThreadCount = 100, 504 kMaxThreadCount = 100,
505 kCachedThreadMemories = 10,
502 }; 506 };
503 507
504 // A thin wrapper around the main thread-tracker that keeps additional 508 // A thin wrapper around the main thread-tracker that keeps additional
505 // information that the global tracker needs to handle joined threads. 509 // information that the global tracker needs to handle joined threads.
506 class ManagedActivityTracker : public ThreadActivityTracker { 510 class ManagedActivityTracker : public ThreadActivityTracker {
507 public: 511 public:
508 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference, 512 ManagedActivityTracker(PersistentMemoryAllocator::Reference mem_reference,
509 void* base, 513 void* base,
510 size_t size); 514 size_t size);
511 ~ManagedActivityTracker() override; 515 ~ManagedActivityTracker() override;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 // The size (in bytes) of memory required by a ThreadActivityTracker to 547 // The size (in bytes) of memory required by a ThreadActivityTracker to
544 // provide the stack-depth requested during construction. 548 // provide the stack-depth requested during construction.
545 const size_t stack_memory_size_; 549 const size_t stack_memory_size_;
546 550
547 // The activity tracker for the currently executing thread. 551 // The activity tracker for the currently executing thread.
548 base::ThreadLocalStorage::Slot this_thread_tracker_; 552 base::ThreadLocalStorage::Slot this_thread_tracker_;
549 553
550 // The number of thread trackers currently active. 554 // The number of thread trackers currently active.
551 std::atomic<int> thread_tracker_count_; 555 std::atomic<int> thread_tracker_count_;
552 556
553 // A cache of thread-tracker memories that have been previously freed and 557 // A caching memory allocator for thread-tracker objects.
554 // thus can be re-used instead of allocating new ones. 558 ActivityTrackerMemoryAllocator thread_tracker_allocator_;
555 ThreadSafeStack<PersistentMemoryAllocator::Reference> available_memories_; 559 base::Lock thread_tracker_allocator_lock_;
556 560
557 // The active global activity tracker. 561 // The active global activity tracker.
558 static GlobalActivityTracker* g_tracker_; 562 static GlobalActivityTracker* g_tracker_;
559 563
560 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker); 564 DISALLOW_COPY_AND_ASSIGN(GlobalActivityTracker);
561 }; 565 };
562 566
563 567
564 // Record entry in to and out of an arbitrary block of code. 568 // Record entry in to and out of an arbitrary block of code.
565 class BASE_EXPORT ScopedActivity 569 class BASE_EXPORT ScopedActivity
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 explicit ScopedProcessWaitActivity(const base::Process* process); 653 explicit ScopedProcessWaitActivity(const base::Process* process);
650 private: 654 private:
651 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity); 655 DISALLOW_COPY_AND_ASSIGN(ScopedProcessWaitActivity);
652 }; 656 };
653 #endif 657 #endif
654 658
655 } // namespace debug 659 } // namespace debug
656 } // namespace base 660 } // namespace base
657 661
658 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_ 662 #endif // BASE_DEBUG_ACTIVITY_TRACKER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698