| Index: src/heap/gc-tracer.cc
|
| diff --git a/src/heap/gc-tracer.cc b/src/heap/gc-tracer.cc
|
| index 50b85e4df1c353dca5c036ae301b1345a8f90e57..c4a118afb79245594ea8fee05ceea6e95f66190b 100644
|
| --- a/src/heap/gc-tracer.cc
|
| +++ b/src/heap/gc-tracer.cc
|
| @@ -45,23 +45,6 @@ GCTracer::Scope::~Scope() {
|
| }
|
|
|
|
|
| -GCTracer::AllocationEvent::AllocationEvent(double duration,
|
| - size_t allocation_in_bytes) {
|
| - duration_ = duration;
|
| - allocation_in_bytes_ = allocation_in_bytes;
|
| -}
|
| -
|
| -
|
| -GCTracer::ContextDisposalEvent::ContextDisposalEvent(double time) {
|
| - time_ = time;
|
| -}
|
| -
|
| -
|
| -GCTracer::SurvivalEvent::SurvivalEvent(double promotion_ratio) {
|
| - promotion_ratio_ = promotion_ratio;
|
| -}
|
| -
|
| -
|
| GCTracer::Event::Event(Type type, const char* gc_reason,
|
| const char* collector_reason)
|
| : type(type),
|
| @@ -202,7 +185,6 @@ void GCTracer::Start(GarbageCollector collector, const char* gc_reason,
|
| }
|
| }
|
|
|
| -
|
| void GCTracer::Stop(GarbageCollector collector) {
|
| start_counter_--;
|
| if (start_counter_ != 0) {
|
| @@ -233,6 +215,7 @@ void GCTracer::Stop(GarbageCollector collector) {
|
| heap_->isolate()->counters()->aggregated_memory_heap_used()->AddSample(
|
| current_.end_time, used_memory);
|
|
|
| + double duration = current_.end_time - current_.start_time;
|
| if (current_.type == Event::SCAVENGER) {
|
| current_.incremental_marking_steps =
|
| current_.cumulative_incremental_marking_steps -
|
| @@ -246,7 +229,10 @@ void GCTracer::Stop(GarbageCollector collector) {
|
| current_.pure_incremental_marking_duration =
|
| current_.cumulative_pure_incremental_marking_duration -
|
| previous_.cumulative_pure_incremental_marking_duration;
|
| - scavenger_events_.push_front(current_);
|
| + recorded_scavenges_total_.Push(
|
| + MakeBytesAndDuration(current_.new_space_object_size, duration));
|
| + recorded_scavenges_survived_.Push(MakeBytesAndDuration(
|
| + current_.survived_new_space_object_size, duration));
|
| } else if (current_.type == Event::INCREMENTAL_MARK_COMPACTOR) {
|
| current_.incremental_marking_steps =
|
| current_.cumulative_incremental_marking_steps -
|
| @@ -265,20 +251,24 @@ void GCTracer::Stop(GarbageCollector collector) {
|
| previous_incremental_mark_compactor_event_
|
| .cumulative_pure_incremental_marking_duration;
|
| longest_incremental_marking_step_ = 0.0;
|
| - incremental_mark_compactor_events_.push_front(current_);
|
| + recorded_incremental_marking_steps_.Push(
|
| + MakeBytesAndDuration(current_.incremental_marking_bytes,
|
| + current_.pure_incremental_marking_duration));
|
| + recorded_incremental_mark_compacts_.Push(
|
| + MakeBytesAndDuration(current_.start_object_size, duration));
|
| combined_mark_compact_speed_cache_ = 0.0;
|
| } else {
|
| DCHECK(current_.incremental_marking_bytes == 0);
|
| DCHECK(current_.incremental_marking_duration == 0);
|
| DCHECK(current_.pure_incremental_marking_duration == 0);
|
| longest_incremental_marking_step_ = 0.0;
|
| - mark_compactor_events_.push_front(current_);
|
| + recorded_mark_compacts_.Push(
|
| + MakeBytesAndDuration(current_.start_object_size, duration));
|
| combined_mark_compact_speed_cache_ = 0.0;
|
| }
|
|
|
| // TODO(ernstm): move the code below out of GCTracer.
|
|
|
| - double duration = current_.end_time - current_.start_time;
|
| double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0);
|
|
|
| heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator,
|
| @@ -336,12 +326,12 @@ void GCTracer::SampleAllocation(double current_ms,
|
| void GCTracer::AddAllocation(double current_ms) {
|
| allocation_time_ms_ = current_ms;
|
| if (allocation_duration_since_gc_ > 0) {
|
| - new_space_allocation_events_.push_front(
|
| - AllocationEvent(allocation_duration_since_gc_,
|
| - new_space_allocation_in_bytes_since_gc_));
|
| - old_generation_allocation_events_.push_front(
|
| - AllocationEvent(allocation_duration_since_gc_,
|
| - old_generation_allocation_in_bytes_since_gc_));
|
| + recorded_new_generation_allocations_.Push(
|
| + MakeBytesAndDuration(new_space_allocation_in_bytes_since_gc_,
|
| + allocation_duration_since_gc_));
|
| + recorded_old_generation_allocations_.Push(
|
| + MakeBytesAndDuration(old_generation_allocation_in_bytes_since_gc_,
|
| + allocation_duration_since_gc_));
|
| }
|
| allocation_duration_since_gc_ = 0;
|
| new_space_allocation_in_bytes_since_gc_ = 0;
|
| @@ -350,19 +340,19 @@ void GCTracer::AddAllocation(double current_ms) {
|
|
|
|
|
| void GCTracer::AddContextDisposalTime(double time) {
|
| - context_disposal_events_.push_front(ContextDisposalEvent(time));
|
| + recorded_context_disposal_times_.Push(time);
|
| }
|
|
|
|
|
| void GCTracer::AddCompactionEvent(double duration,
|
| intptr_t live_bytes_compacted) {
|
| - compaction_events_.push_front(
|
| - CompactionEvent(duration, live_bytes_compacted));
|
| + recorded_compactions_.Push(
|
| + MakeBytesAndDuration(live_bytes_compacted, duration));
|
| }
|
|
|
|
|
| void GCTracer::AddSurvivalRatio(double promotion_ratio) {
|
| - survival_events_.push_front(SurvivalEvent(promotion_ratio));
|
| + recorded_survival_ratios_.Push(promotion_ratio);
|
| }
|
|
|
|
|
| @@ -669,128 +659,62 @@ void GCTracer::PrintNVP() const {
|
| }
|
| }
|
|
|
| -
|
| -double GCTracer::MeanDuration(const EventBuffer& events) const {
|
| - if (events.empty()) return 0.0;
|
| -
|
| - double mean = 0.0;
|
| - EventBuffer::const_iterator iter = events.begin();
|
| - while (iter != events.end()) {
|
| - mean += iter->end_time - iter->start_time;
|
| - ++iter;
|
| - }
|
| -
|
| - return mean / events.size();
|
| +int GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer,
|
| + const BytesAndDuration& initial, double time_ms) {
|
| + BytesAndDuration sum = buffer.Sum(
|
| + [time_ms](BytesAndDuration a, BytesAndDuration b) {
|
| + if (time_ms != 0 && a.second >= time_ms) return a;
|
| + return std::make_pair(a.first + b.first, a.second + b.second);
|
| + },
|
| + initial);
|
| + uint64_t bytes = sum.first;
|
| + double durations = sum.second;
|
| + if (durations == 0.0) return 0;
|
| + double speed = bytes / durations + 0.5;
|
| + const int max_speed = 1024 * MB;
|
| + const int min_speed = 1;
|
| + if (speed >= max_speed) return max_speed;
|
| + if (speed <= min_speed) return min_speed;
|
| + return static_cast<int>(speed);
|
| }
|
|
|
| -
|
| -double GCTracer::MaxDuration(const EventBuffer& events) const {
|
| - if (events.empty()) return 0.0;
|
| -
|
| - double maximum = 0.0f;
|
| - EventBuffer::const_iterator iter = events.begin();
|
| - while (iter != events.end()) {
|
| - maximum = Max(iter->end_time - iter->start_time, maximum);
|
| - ++iter;
|
| - }
|
| -
|
| - return maximum;
|
| +int GCTracer::AverageSpeed(const RingBuffer<BytesAndDuration>& buffer) {
|
| + return AverageSpeed(buffer, MakeBytesAndDuration(0, 0), 0);
|
| }
|
|
|
| -
|
| intptr_t GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const {
|
| if (cumulative_incremental_marking_duration_ == 0.0) return 0;
|
| -
|
| // We haven't completed an entire round of incremental marking, yet.
|
| // Use data from GCTracer instead of data from event buffers.
|
| - if (incremental_mark_compactor_events_.empty()) {
|
| + if (recorded_incremental_marking_steps_.Count() == 0) {
|
| return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ /
|
| cumulative_pure_incremental_marking_duration_);
|
| }
|
| -
|
| - intptr_t bytes = 0;
|
| - double durations = 0.0;
|
| - EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin();
|
| - while (iter != incremental_mark_compactor_events_.end()) {
|
| - bytes += iter->incremental_marking_bytes;
|
| - durations += iter->pure_incremental_marking_duration;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1);
|
| + return AverageSpeed(recorded_incremental_marking_steps_);
|
| }
|
|
|
| -
|
| intptr_t GCTracer::ScavengeSpeedInBytesPerMillisecond(
|
| ScavengeSpeedMode mode) const {
|
| - intptr_t bytes = 0;
|
| - double durations = 0.0;
|
| - EventBuffer::const_iterator iter = scavenger_events_.begin();
|
| - while (iter != scavenger_events_.end()) {
|
| - bytes += mode == kForAllObjects ? iter->new_space_object_size
|
| - : iter->survived_new_space_object_size;
|
| - durations += iter->end_time - iter->start_time;
|
| - ++iter;
|
| + if (mode == kForAllObjects) {
|
| + return AverageSpeed(recorded_scavenges_total_);
|
| + } else {
|
| + return AverageSpeed(recorded_scavenges_survived_);
|
| }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1);
|
| }
|
|
|
| -
|
| intptr_t GCTracer::CompactionSpeedInBytesPerMillisecond() const {
|
| - if (compaction_events_.size() == 0) return 0;
|
| - intptr_t bytes = 0;
|
| - double durations = 0.0;
|
| - CompactionEventBuffer::const_iterator iter = compaction_events_.begin();
|
| - while (iter != compaction_events_.end()) {
|
| - bytes += iter->live_bytes_compacted;
|
| - durations += iter->duration;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<intptr_t>(static_cast<intptr_t>(bytes / durations + 0.5), 1);
|
| + return AverageSpeed(recorded_compactions_);
|
| }
|
|
|
| -
|
| intptr_t GCTracer::MarkCompactSpeedInBytesPerMillisecond() const {
|
| - intptr_t bytes = 0;
|
| - double durations = 0.0;
|
| - EventBuffer::const_iterator iter = mark_compactor_events_.begin();
|
| - while (iter != mark_compactor_events_.end()) {
|
| - bytes += iter->start_object_size;
|
| - durations += iter->end_time - iter->start_time;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1);
|
| + return AverageSpeed(recorded_mark_compacts_);
|
| }
|
|
|
| -
|
| intptr_t GCTracer::FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()
|
| const {
|
| - intptr_t bytes = 0;
|
| - double durations = 0.0;
|
| - EventBuffer::const_iterator iter = incremental_mark_compactor_events_.begin();
|
| - while (iter != incremental_mark_compactor_events_.end()) {
|
| - bytes += iter->start_object_size;
|
| - durations += iter->end_time - iter->start_time;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1);
|
| + return AverageSpeed(recorded_incremental_mark_compacts_);
|
| }
|
|
|
| -
|
| double GCTracer::CombinedMarkCompactSpeedInBytesPerMillisecond() {
|
| if (combined_mark_compact_speed_cache_ > 0)
|
| return combined_mark_compact_speed_cache_;
|
| @@ -816,39 +740,16 @@ double GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond(
|
| double time_ms) const {
|
| size_t bytes = new_space_allocation_in_bytes_since_gc_;
|
| double durations = allocation_duration_since_gc_;
|
| - AllocationEventBuffer::const_iterator iter =
|
| - new_space_allocation_events_.begin();
|
| - const size_t max_bytes = static_cast<size_t>(-1);
|
| - while (iter != new_space_allocation_events_.end() &&
|
| - bytes < max_bytes - bytes && (time_ms == 0 || durations < time_ms)) {
|
| - bytes += iter->allocation_in_bytes_;
|
| - durations += iter->duration_;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| -
|
| - // Make sure the result is at least 1.
|
| - return Max<double>(bytes / durations, 1);
|
| + return AverageSpeed(recorded_new_generation_allocations_,
|
| + MakeBytesAndDuration(bytes, durations), time_ms);
|
| }
|
|
|
| double GCTracer::OldGenerationAllocationThroughputInBytesPerMillisecond(
|
| double time_ms) const {
|
| size_t bytes = old_generation_allocation_in_bytes_since_gc_;
|
| double durations = allocation_duration_since_gc_;
|
| - AllocationEventBuffer::const_iterator iter =
|
| - old_generation_allocation_events_.begin();
|
| - const size_t max_bytes = static_cast<size_t>(-1);
|
| - while (iter != old_generation_allocation_events_.end() &&
|
| - bytes < max_bytes - bytes && (time_ms == 0 || durations < time_ms)) {
|
| - bytes += iter->allocation_in_bytes_;
|
| - durations += iter->duration_;
|
| - ++iter;
|
| - }
|
| -
|
| - if (durations == 0.0) return 0;
|
| - // Make sure the result is at least 1.
|
| - return Max<double>(bytes / durations, 1);
|
| + return AverageSpeed(recorded_old_generation_allocations_,
|
| + MakeBytesAndDuration(bytes, durations), time_ms);
|
| }
|
|
|
| double GCTracer::AllocationThroughputInBytesPerMillisecond(
|
| @@ -869,42 +770,27 @@ size_t GCTracer::CurrentOldGenerationAllocationThroughputInBytesPerMillisecond()
|
| kThroughputTimeFrameMs);
|
| }
|
|
|
| -
|
| double GCTracer::ContextDisposalRateInMilliseconds() const {
|
| - if (context_disposal_events_.size() < kRingBufferMaxSize) return 0.0;
|
| -
|
| + if (recorded_context_disposal_times_.Count() <
|
| + recorded_context_disposal_times_.kSize)
|
| + return 0.0;
|
| double begin = heap_->MonotonicallyIncreasingTimeInMs();
|
| - double end = 0.0;
|
| - ContextDisposalEventBuffer::const_iterator iter =
|
| - context_disposal_events_.begin();
|
| - while (iter != context_disposal_events_.end()) {
|
| - end = iter->time_;
|
| - ++iter;
|
| - }
|
| -
|
| - return (begin - end) / context_disposal_events_.size();
|
| + double end = recorded_context_disposal_times_.Sum(
|
| + [](double a, double b) { return b; }, 0.0);
|
| + return (begin - end) / recorded_context_disposal_times_.Count();
|
| }
|
|
|
| -
|
| double GCTracer::AverageSurvivalRatio() const {
|
| - if (survival_events_.size() == 0) return 0.0;
|
| -
|
| - double sum_of_rates = 0.0;
|
| - SurvivalEventBuffer::const_iterator iter = survival_events_.begin();
|
| - while (iter != survival_events_.end()) {
|
| - sum_of_rates += iter->promotion_ratio_;
|
| - ++iter;
|
| - }
|
| -
|
| - return sum_of_rates / static_cast<double>(survival_events_.size());
|
| + if (recorded_survival_ratios_.Count() == 0) return 0.0;
|
| + double sum = recorded_survival_ratios_.Sum(
|
| + [](double a, double b) { return a + b; }, 0.0);
|
| + return sum / recorded_survival_ratios_.Count();
|
| }
|
|
|
| -
|
| bool GCTracer::SurvivalEventsRecorded() const {
|
| - return survival_events_.size() > 0;
|
| + return recorded_survival_ratios_.Count() > 0;
|
| }
|
|
|
| -
|
| -void GCTracer::ResetSurvivalEvents() { survival_events_.reset(); }
|
| +void GCTracer::ResetSurvivalEvents() { recorded_survival_ratios_.Reset(); }
|
| } // namespace internal
|
| } // namespace v8
|
|
|