summaryrefslogtreecommitdiff
path: root/deps/v8/src/heap/gc-tracer.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/heap/gc-tracer.h')
-rw-r--r--deps/v8/src/heap/gc-tracer.h374
1 files changed, 134 insertions, 240 deletions
diff --git a/deps/v8/src/heap/gc-tracer.h b/deps/v8/src/heap/gc-tracer.h
index e8ec168187..9ea3cce8fa 100644
--- a/deps/v8/src/heap/gc-tracer.h
+++ b/deps/v8/src/heap/gc-tracer.h
@@ -6,88 +6,114 @@
#define V8_HEAP_GC_TRACER_H_
#include "src/base/platform/platform.h"
+#include "src/counters.h"
#include "src/globals.h"
namespace v8 {
namespace internal {
-// A simple ring buffer class with maximum size known at compile time.
-// The class only implements the functionality required in GCTracer.
-template <typename T, size_t MAX_SIZE>
+template <typename T>
class RingBuffer {
public:
- class const_iterator {
- public:
- const_iterator() : index_(0), elements_(NULL) {}
-
- const_iterator(size_t index, const T* elements)
- : index_(index), elements_(elements) {}
-
- bool operator==(const const_iterator& rhs) const {
- return elements_ == rhs.elements_ && index_ == rhs.index_;
- }
-
- bool operator!=(const const_iterator& rhs) const {
- return elements_ != rhs.elements_ || index_ != rhs.index_;
+ RingBuffer() { Reset(); }
+ static const int kSize = 10;
+ void Push(const T& value) {
+ if (count_ == kSize) {
+ elements_[start_++] = value;
+ if (start_ == kSize) start_ = 0;
+ } else {
+ DCHECK_EQ(start_, 0);
+ elements_[count_++] = value;
}
+ }
- operator const T*() const { return elements_ + index_; }
-
- const T* operator->() const { return elements_ + index_; }
-
- const T& operator*() const { return elements_[index_]; }
-
- const_iterator& operator++() {
- index_ = (index_ + 1) % (MAX_SIZE + 1);
- return *this;
- }
+ int Count() const { return count_; }
- const_iterator& operator--() {
- index_ = (index_ + MAX_SIZE) % (MAX_SIZE + 1);
- return *this;
+ template <typename Callback>
+ T Sum(Callback callback, const T& initial) const {
+ int j = start_ + count_ - 1;
+ if (j >= kSize) j -= kSize;
+ T result = initial;
+ for (int i = 0; i < count_; i++) {
+ result = callback(result, elements_[j]);
+ if (--j == -1) j += kSize;
}
-
- private:
- size_t index_;
- const T* elements_;
- };
-
- RingBuffer() : begin_(0), end_(0) {}
-
- bool empty() const { return begin_ == end_; }
- size_t size() const {
- return (end_ - begin_ + MAX_SIZE + 1) % (MAX_SIZE + 1);
- }
- const_iterator begin() const { return const_iterator(begin_, elements_); }
- const_iterator end() const { return const_iterator(end_, elements_); }
- const_iterator back() const { return --end(); }
- void push_back(const T& element) {
- elements_[end_] = element;
- end_ = (end_ + 1) % (MAX_SIZE + 1);
- if (end_ == begin_) begin_ = (begin_ + 1) % (MAX_SIZE + 1);
- }
- void push_front(const T& element) {
- begin_ = (begin_ + MAX_SIZE) % (MAX_SIZE + 1);
- if (begin_ == end_) end_ = (end_ + MAX_SIZE) % (MAX_SIZE + 1);
- elements_[begin_] = element;
+ return result;
}
- void reset() {
- begin_ = 0;
- end_ = 0;
- }
+ void Reset() { start_ = count_ = 0; }
private:
- T elements_[MAX_SIZE + 1];
- size_t begin_;
- size_t end_;
-
+ T elements_[kSize];
+ int start_;
+ int count_;
DISALLOW_COPY_AND_ASSIGN(RingBuffer);
};
+typedef std::pair<uint64_t, double> BytesAndDuration;
+
+inline BytesAndDuration MakeBytesAndDuration(uint64_t bytes, double duration) {
+ return std::make_pair(bytes, duration);
+}
enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
+#define TRACER_SCOPES(F) \
+ F(EXTERNAL_WEAK_GLOBAL_HANDLES) \
+ F(MC_CLEAR) \
+ F(MC_CLEAR_CODE_FLUSH) \
+ F(MC_CLEAR_DEPENDENT_CODE) \
+ F(MC_CLEAR_GLOBAL_HANDLES) \
+ F(MC_CLEAR_MAPS) \
+ F(MC_CLEAR_SLOTS_BUFFER) \
+ F(MC_CLEAR_STORE_BUFFER) \
+ F(MC_CLEAR_STRING_TABLE) \
+ F(MC_CLEAR_WEAK_CELLS) \
+ F(MC_CLEAR_WEAK_COLLECTIONS) \
+ F(MC_CLEAR_WEAK_LISTS) \
+ F(MC_EVACUATE) \
+ F(MC_EVACUATE_CANDIDATES) \
+ F(MC_EVACUATE_CLEAN_UP) \
+ F(MC_EVACUATE_COPY) \
+ F(MC_EVACUATE_UPDATE_POINTERS) \
+ F(MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED) \
+ F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED) \
+ F(MC_EVACUATE_UPDATE_POINTERS_TO_NEW) \
+ F(MC_EVACUATE_UPDATE_POINTERS_WEAK) \
+ F(MC_EXTERNAL_EPILOGUE) \
+ F(MC_EXTERNAL_PROLOGUE) \
+ F(MC_FINISH) \
+ F(MC_INCREMENTAL_FINALIZE) \
+ F(MC_INCREMENTAL_EXTERNAL_EPILOGUE) \
+ F(MC_INCREMENTAL_EXTERNAL_PROLOGUE) \
+ F(MC_MARK) \
+ F(MC_MARK_FINISH_INCREMENTAL) \
+ F(MC_MARK_PREPARE_CODE_FLUSH) \
+ F(MC_MARK_ROOTS) \
+ F(MC_MARK_WEAK_CLOSURE) \
+ F(MC_MARK_WEAK_CLOSURE_EPHEMERAL) \
+ F(MC_MARK_WEAK_CLOSURE_WEAK_HANDLES) \
+ F(MC_MARK_WEAK_CLOSURE_WEAK_ROOTS) \
+ F(MC_MARK_WEAK_CLOSURE_HARMONY) \
+ F(MC_SWEEP) \
+ F(MC_SWEEP_CODE) \
+ F(MC_SWEEP_MAP) \
+ F(MC_SWEEP_OLD) \
+ F(SCAVENGER_CODE_FLUSH_CANDIDATES) \
+ F(SCAVENGER_EXTERNAL_EPILOGUE) \
+ F(SCAVENGER_EXTERNAL_PROLOGUE) \
+ F(SCAVENGER_OBJECT_GROUPS) \
+ F(SCAVENGER_OLD_TO_NEW_POINTERS) \
+ F(SCAVENGER_ROOTS) \
+ F(SCAVENGER_SCAVENGE) \
+ F(SCAVENGER_SEMISPACE) \
+ F(SCAVENGER_WEAK)
+
+#define TRACE_GC(tracer, scope_id) \
+ GCTracer::Scope::ScopeId gc_tracer_scope_id(scope_id); \
+ GCTracer::Scope gc_tracer_scope(tracer, gc_tracer_scope_id); \
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8"), \
+ GCTracer::Scope::Name(gc_tracer_scope_id))
// GCTracer collects and prints ONE line after each garbage collector
// invocation IFF --trace_gc is used.
@@ -97,112 +123,26 @@ class GCTracer {
class Scope {
public:
enum ScopeId {
- EXTERNAL,
- MC_CLEAR,
- MC_CLEAR_CODE_FLUSH,
- MC_CLEAR_DEPENDENT_CODE,
- MC_CLEAR_GLOBAL_HANDLES,
- MC_CLEAR_MAPS,
- MC_CLEAR_SLOTS_BUFFER,
- MC_CLEAR_STORE_BUFFER,
- MC_CLEAR_STRING_TABLE,
- MC_CLEAR_WEAK_CELLS,
- MC_CLEAR_WEAK_COLLECTIONS,
- MC_CLEAR_WEAK_LISTS,
- MC_EVACUATE,
- MC_EVACUATE_CANDIDATES,
- MC_EVACUATE_CLEAN_UP,
- MC_EVACUATE_NEW_SPACE,
- MC_EVACUATE_UPDATE_POINTERS,
- MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED,
- MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED,
- MC_EVACUATE_UPDATE_POINTERS_TO_NEW,
- MC_EVACUATE_UPDATE_POINTERS_WEAK,
- MC_FINISH,
- MC_INCREMENTAL_FINALIZE,
- MC_MARK,
- MC_MARK_FINISH_INCREMENTAL,
- MC_MARK_PREPARE_CODE_FLUSH,
- MC_MARK_ROOTS,
- MC_MARK_WEAK_CLOSURE,
- MC_SWEEP,
- MC_SWEEP_CODE,
- MC_SWEEP_MAP,
- MC_SWEEP_OLD,
- SCAVENGER_CODE_FLUSH_CANDIDATES,
- SCAVENGER_OBJECT_GROUPS,
- SCAVENGER_OLD_TO_NEW_POINTERS,
- SCAVENGER_ROOTS,
- SCAVENGER_SCAVENGE,
- SCAVENGER_SEMISPACE,
- SCAVENGER_WEAK,
- NUMBER_OF_SCOPES
+#define DEFINE_SCOPE(scope) scope,
+ TRACER_SCOPES(DEFINE_SCOPE)
+#undef DEFINE_SCOPE
+ NUMBER_OF_SCOPES
};
Scope(GCTracer* tracer, ScopeId scope);
~Scope();
+ static const char* Name(ScopeId id);
private:
GCTracer* tracer_;
ScopeId scope_;
double start_time_;
+ RuntimeCallTimer timer_;
DISALLOW_COPY_AND_ASSIGN(Scope);
};
- class AllocationEvent {
- public:
- // Default constructor leaves the event uninitialized.
- AllocationEvent() {}
-
- AllocationEvent(double duration, size_t allocation_in_bytes);
-
- // Time spent in the mutator during the end of the last sample to the
- // beginning of the next sample.
- double duration_;
-
- // Memory allocated in the new space during the end of the last sample
- // to the beginning of the next sample
- size_t allocation_in_bytes_;
- };
-
-
- class CompactionEvent {
- public:
- CompactionEvent() : duration(0), live_bytes_compacted(0) {}
-
- CompactionEvent(double duration, intptr_t live_bytes_compacted)
- : duration(duration), live_bytes_compacted(live_bytes_compacted) {}
-
- double duration;
- intptr_t live_bytes_compacted;
- };
-
-
- class ContextDisposalEvent {
- public:
- // Default constructor leaves the event uninitialized.
- ContextDisposalEvent() {}
-
- explicit ContextDisposalEvent(double time);
-
- // Time when context disposal event happened.
- double time_;
- };
-
-
- class SurvivalEvent {
- public:
- // Default constructor leaves the event uninitialized.
- SurvivalEvent() {}
-
- explicit SurvivalEvent(double survival_ratio);
-
- double promotion_ratio_;
- };
-
-
class Event {
public:
enum Type {
@@ -307,19 +247,6 @@ class GCTracer {
double scopes[Scope::NUMBER_OF_SCOPES];
};
- static const size_t kRingBufferMaxSize = 10;
-
- typedef RingBuffer<Event, kRingBufferMaxSize> EventBuffer;
-
- typedef RingBuffer<AllocationEvent, kRingBufferMaxSize> AllocationEventBuffer;
-
- typedef RingBuffer<ContextDisposalEvent, kRingBufferMaxSize>
- ContextDisposalEventBuffer;
-
- typedef RingBuffer<CompactionEvent, kRingBufferMaxSize> CompactionEventBuffer;
-
- typedef RingBuffer<SurvivalEvent, kRingBufferMaxSize> SurvivalEventBuffer;
-
static const int kThroughputTimeFrameMs = 5000;
explicit GCTracer(Heap* heap);
@@ -369,63 +296,27 @@ class GCTracer {
return cumulative_sweeping_duration_;
}
- // Compute the mean duration of the last scavenger events. Returns 0 if no
- // events have been recorded.
- double MeanScavengerDuration() const {
- return MeanDuration(scavenger_events_);
- }
-
- // Compute the max duration of the last scavenger events. Returns 0 if no
- // events have been recorded.
- double MaxScavengerDuration() const { return MaxDuration(scavenger_events_); }
-
- // Compute the mean duration of the last mark compactor events. Returns 0 if
- // no events have been recorded.
- double MeanMarkCompactorDuration() const {
- return MeanDuration(mark_compactor_events_);
- }
-
- // Compute the max duration of the last mark compactor events. Return 0 if no
- // events have been recorded.
- double MaxMarkCompactorDuration() const {
- return MaxDuration(mark_compactor_events_);
- }
-
- // Compute the mean duration of the last incremental mark compactor
- // events. Returns 0 if no events have been recorded.
- double MeanIncrementalMarkCompactorDuration() const {
- return MeanDuration(incremental_mark_compactor_events_);
- }
-
- // Compute the mean step duration of the last incremental marking round.
- // Returns 0 if no incremental marking round has been completed.
- double MeanIncrementalMarkingDuration() const;
-
- // Compute the max step duration of the last incremental marking round.
- // Returns 0 if no incremental marking round has been completed.
- double MaxIncrementalMarkingDuration() const;
-
// Compute the average incremental marking speed in bytes/millisecond.
// Returns 0 if no events have been recorded.
- intptr_t IncrementalMarkingSpeedInBytesPerMillisecond() const;
+ double IncrementalMarkingSpeedInBytesPerMillisecond() const;
// Compute the average scavenge speed in bytes/millisecond.
// Returns 0 if no events have been recorded.
- intptr_t ScavengeSpeedInBytesPerMillisecond(
+ double ScavengeSpeedInBytesPerMillisecond(
ScavengeSpeedMode mode = kForAllObjects) const;
// Compute the average compaction speed in bytes/millisecond.
// Returns 0 if not enough events have been recorded.
- intptr_t CompactionSpeedInBytesPerMillisecond() const;
+ double CompactionSpeedInBytesPerMillisecond() const;
// Compute the average mark-sweep speed in bytes/millisecond.
// Returns 0 if no events have been recorded.
- intptr_t MarkCompactSpeedInBytesPerMillisecond() const;
+ double MarkCompactSpeedInBytesPerMillisecond() const;
// Compute the average incremental mark-sweep finalize speed in
// bytes/millisecond.
// Returns 0 if no events have been recorded.
- intptr_t FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() const;
+ double FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() const;
// Compute the overall mark compact speed including incremental steps
// and the final mark-compact step.
@@ -433,29 +324,29 @@ class GCTracer {
// Allocation throughput in the new space in bytes/millisecond.
// Returns 0 if no allocation events have been recorded.
- size_t NewSpaceAllocationThroughputInBytesPerMillisecond(
+ double NewSpaceAllocationThroughputInBytesPerMillisecond(
double time_ms = 0) const;
// Allocation throughput in the old generation in bytes/millisecond in the
// last time_ms milliseconds.
// Returns 0 if no allocation events have been recorded.
- size_t OldGenerationAllocationThroughputInBytesPerMillisecond(
+ double OldGenerationAllocationThroughputInBytesPerMillisecond(
double time_ms = 0) const;
// Allocation throughput in heap in bytes/millisecond in the last time_ms
// milliseconds.
// Returns 0 if no allocation events have been recorded.
- size_t AllocationThroughputInBytesPerMillisecond(double time_ms) const;
+ double AllocationThroughputInBytesPerMillisecond(double time_ms) const;
// Allocation throughput in heap in bytes/milliseconds in the last
// kThroughputTimeFrameMs seconds.
// Returns 0 if no allocation events have been recorded.
- size_t CurrentAllocationThroughputInBytesPerMillisecond() const;
+ double CurrentAllocationThroughputInBytesPerMillisecond() const;
// Allocation throughput in old generation in bytes/milliseconds in the last
// kThroughputTimeFrameMs seconds.
// Returns 0 if no allocation events have been recorded.
- size_t CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() const;
+ double CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() const;
// Computes the context disposal rate in milliseconds. It takes the time
// frame of the first recorded context disposal to the current time and
@@ -474,6 +365,13 @@ class GCTracer {
// Discard all recorded survival events.
void ResetSurvivalEvents();
+ // Returns the average speed of the events in the buffer.
+ // If the buffer is empty, the result is 0.
+ // Otherwise, the result is between 1 byte/ms and 1 GB/ms.
+ static double AverageSpeed(const RingBuffer<BytesAndDuration>& buffer);
+ static double AverageSpeed(const RingBuffer<BytesAndDuration>& buffer,
+ const BytesAndDuration& initial, double time_ms);
+
private:
// Print one detailed trace line in name=value format.
// TODO(ernstm): Move to Heap.
@@ -487,12 +385,6 @@ class GCTracer {
// it can be included in later crash dumps.
void Output(const char* format, ...) const;
- // Compute the mean duration of the events in the given ring buffer.
- double MeanDuration(const EventBuffer& events) const;
-
- // Compute the max duration of the events in the given ring buffer.
- double MaxDuration(const EventBuffer& events) const;
-
void ClearMarkCompactStatistics() {
cumulative_incremental_marking_steps_ = 0;
cumulative_incremental_marking_bytes_ = 0;
@@ -506,6 +398,16 @@ class GCTracer {
cumulative_sweeping_duration_ = 0;
}
+ double TotalExternalTime() const {
+ return current_.scopes[Scope::EXTERNAL_WEAK_GLOBAL_HANDLES] +
+ current_.scopes[Scope::MC_EXTERNAL_EPILOGUE] +
+ current_.scopes[Scope::MC_EXTERNAL_PROLOGUE] +
+ current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE] +
+ current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE] +
+ current_.scopes[Scope::SCAVENGER_EXTERNAL_EPILOGUE] +
+ current_.scopes[Scope::SCAVENGER_EXTERNAL_PROLOGUE];
+ }
+
// Pointer to the heap that owns this tracer.
Heap* heap_;
@@ -519,28 +421,6 @@ class GCTracer {
// Previous INCREMENTAL_MARK_COMPACTOR event.
Event previous_incremental_mark_compactor_event_;
- // RingBuffers for SCAVENGER events.
- EventBuffer scavenger_events_;
-
- // RingBuffers for MARK_COMPACTOR events.
- EventBuffer mark_compactor_events_;
-
- // RingBuffers for INCREMENTAL_MARK_COMPACTOR events.
- EventBuffer incremental_mark_compactor_events_;
-
- // RingBuffer for allocation events.
- AllocationEventBuffer new_space_allocation_events_;
- AllocationEventBuffer old_generation_allocation_events_;
-
- // RingBuffer for context disposal events.
- ContextDisposalEventBuffer context_disposal_events_;
-
- // RingBuffer for compaction events.
- CompactionEventBuffer compaction_events_;
-
- // RingBuffer for survival events.
- SurvivalEventBuffer survival_events_;
-
// Cumulative number of incremental marking steps since creation of tracer.
int cumulative_incremental_marking_steps_;
@@ -597,6 +477,20 @@ class GCTracer {
// Counts how many tracers were started without stopping.
int start_counter_;
+ // Separate timer used for --runtime_call_stats
+ RuntimeCallTimer timer_;
+
+ RingBuffer<BytesAndDuration> recorded_incremental_marking_steps_;
+ RingBuffer<BytesAndDuration> recorded_scavenges_total_;
+ RingBuffer<BytesAndDuration> recorded_scavenges_survived_;
+ RingBuffer<BytesAndDuration> recorded_compactions_;
+ RingBuffer<BytesAndDuration> recorded_mark_compacts_;
+ RingBuffer<BytesAndDuration> recorded_incremental_mark_compacts_;
+ RingBuffer<BytesAndDuration> recorded_new_generation_allocations_;
+ RingBuffer<BytesAndDuration> recorded_old_generation_allocations_;
+ RingBuffer<double> recorded_context_disposal_times_;
+ RingBuffer<double> recorded_survival_ratios_;
+
DISALLOW_COPY_AND_ASSIGN(GCTracer);
};
} // namespace internal