1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_CPPGC_STATS_COLLECTOR_H_ 6 #define V8_HEAP_CPPGC_STATS_COLLECTOR_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <vector> 12 13 #include "src/base/macros.h" 14 #include "src/base/platform/time.h" 15 16 namespace cppgc { 17 namespace internal { 18 19 // Sink for various time and memory statistics. 20 class V8_EXPORT_PRIVATE StatsCollector final { 21 public: 22 // POD to hold interesting data accumulated during a garbage collection cycle. 23 // 24 // The event is always fully populated when looking at previous events but 25 // may only be partially populated when looking at the current event. 26 struct Event final { 27 // Marked bytes collected during marking. 28 size_t marked_bytes = 0; 29 }; 30 31 // Observer for allocated object size. May be used to implement heap growing 32 // heuristics. 33 class AllocationObserver { 34 public: 35 // Called after observing at least 36 // StatsCollector::kAllocationThresholdBytes changed bytes through 37 // allocation or explicit free. Reports both, negative and positive 38 // increments, to allow observer to decide whether absolute values or only 39 // the deltas is interesting. 40 // 41 // May trigger GC. 42 virtual void AllocatedObjectSizeIncreased(size_t) = 0; 43 virtual void AllocatedObjectSizeDecreased(size_t) = 0; 44 45 // Called when the exact size of allocated object size is known. In 46 // practice, this is after marking when marked bytes == allocated bytes. 47 // 48 // Must not trigger GC synchronously. 49 virtual void ResetAllocatedObjectSize(size_t) = 0; 50 }; 51 52 // Observers are implemented using virtual calls. Avoid notifications below 53 // reasonably interesting sizes. 54 static constexpr size_t kAllocationThresholdBytes = 1024; 55 56 StatsCollector() = default; 57 StatsCollector(const StatsCollector&) = delete; 58 StatsCollector& operator=(const StatsCollector&) = delete; 59 60 void RegisterObserver(AllocationObserver*); 61 void UnregisterObserver(AllocationObserver*); 62 63 void NotifyAllocation(size_t); 64 void NotifyExplicitFree(size_t); 65 // Safepoints should only be invoked when garabge collections are possible. 66 // This is necessary as increments and decrements are reported as close to 67 // their actual allocation/reclamation as possible. 68 void NotifySafePointForConservativeCollection(); 69 70 // Indicates a new garbage collection cycle. 71 void NotifyMarkingStarted(); 72 // Indicates that marking of the current garbage collection cycle is 73 // completed. 74 void NotifyMarkingCompleted(size_t marked_bytes); 75 // Indicates the end of a garbage collection cycle. This means that sweeping 76 // is finished at this point. 77 const Event& NotifySweepingCompleted(); 78 79 // Size of live objects in bytes on the heap. Based on the most recent marked 80 // bytes and the bytes allocated since last marking. 81 size_t allocated_object_size() const; 82 83 double GetRecentAllocationSpeedInBytesPerMs() const; 84 85 private: 86 enum class GarbageCollectionState : uint8_t { 87 kNotRunning, 88 kMarking, 89 kSweeping 90 }; 91 92 // Invokes |callback| for all registered observers. 93 template <typename Callback> 94 void ForAllAllocationObservers(Callback callback); 95 96 void AllocatedObjectSizeSafepointImpl(); 97 98 // Allocated bytes since the end of marking. These bytes are reset after 99 // marking as they are accounted in marked_bytes then. May be negative in case 100 // an object was explicitly freed that was marked as live in the previous 101 // cycle. 102 int64_t allocated_bytes_since_end_of_marking_ = 0; 103 v8::base::TimeTicks time_of_last_end_of_marking_ = v8::base::TimeTicks::Now(); 104 // Counters for allocation and free. The individual values are never negative 105 // but their delta may be because of the same reason the overall 106 // allocated_bytes_since_end_of_marking_ may be negative. Keep integer 107 // arithmetic for simplicity. 108 int64_t allocated_bytes_since_safepoint_ = 0; 109 int64_t explicitly_freed_bytes_since_safepoint_ = 0; 110 111 // vector to allow fast iteration of observers. Register/Unregisters only 112 // happens on startup/teardown. 113 std::vector<AllocationObserver*> allocation_observers_; 114 115 GarbageCollectionState gc_state_ = GarbageCollectionState::kNotRunning; 116 117 // The event being filled by the current GC cycle between NotifyMarkingStarted 118 // and NotifySweepingFinished. 119 Event current_; 120 // The previous GC event which is populated at NotifySweepingFinished. 121 Event previous_; 122 }; 123 124 template <typename Callback> ForAllAllocationObservers(Callback callback)125void StatsCollector::ForAllAllocationObservers(Callback callback) { 126 for (AllocationObserver* observer : allocation_observers_) { 127 callback(observer); 128 } 129 } 130 131 } // namespace internal 132 } // namespace cppgc 133 134 #endif // V8_HEAP_CPPGC_STATS_COLLECTOR_H_ 135