Index: src/heap/gc-tracer.cc |
diff --git a/src/heap/gc-tracer.cc b/src/heap/gc-tracer.cc |
index e4d992c9e793c499e8fa9173db37b7b2ffe6a725..6ca724e5a1ef18158fa1b436f69ca5149df5ec80 100644 |
--- a/src/heap/gc-tracer.cc |
+++ b/src/heap/gc-tracer.cc |
@@ -105,6 +105,7 @@ GCTracer::GCTracer(Heap* heap) |
allocation_duration_since_gc_(0.0), |
new_space_allocation_in_bytes_since_gc_(0), |
old_generation_allocation_in_bytes_since_gc_(0), |
+ combined_mark_compact_speed_cache_(0.0), |
start_counter_(0) { |
current_ = Event(Event::START, NULL, NULL); |
current_.end_time = base::OS::TimeCurrentMillis(); |
@@ -226,12 +227,14 @@ void GCTracer::Stop(GarbageCollector collector) { |
.cumulative_pure_incremental_marking_duration; |
longest_incremental_marking_step_ = 0.0; |
incremental_mark_compactor_events_.push_front(current_); |
+ 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_); |
+ combined_mark_compact_speed_cache_ = 0.0; |
} |
// TODO(ernstm): move the code below out of GCTracer. |
@@ -292,10 +295,9 @@ void GCTracer::AddAllocation(double current_ms) { |
allocation_time_ms_ = current_ms; |
new_space_allocation_events_.push_front(AllocationEvent( |
allocation_duration_since_gc_, new_space_allocation_in_bytes_since_gc_)); |
- allocation_events_.push_front( |
+ old_generation_allocation_events_.push_front( |
AllocationEvent(allocation_duration_since_gc_, |
- new_space_allocation_in_bytes_since_gc_ + |
- old_generation_allocation_in_bytes_since_gc_)); |
+ old_generation_allocation_in_bytes_since_gc_)); |
allocation_duration_since_gc_ = 0; |
new_space_allocation_in_bytes_since_gc_ = 0; |
old_generation_allocation_in_bytes_since_gc_ = 0; |
@@ -560,8 +562,8 @@ intptr_t GCTracer::IncrementalMarkingSpeedInBytesPerMillisecond() const { |
} |
if (durations == 0.0) return 0; |
- |
- return static_cast<intptr_t>(bytes / durations); |
+ // Make sure the result is at least 1. |
+ return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1); |
} |
@@ -576,8 +578,8 @@ intptr_t GCTracer::ScavengeSpeedInBytesPerMillisecond() const { |
} |
if (durations == 0.0) return 0; |
- |
- return static_cast<intptr_t>(bytes / durations); |
+ // Make sure the result is at least 1. |
+ return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1); |
} |
@@ -592,8 +594,8 @@ intptr_t GCTracer::MarkCompactSpeedInBytesPerMillisecond() const { |
} |
if (durations == 0.0) return 0; |
- |
- return static_cast<intptr_t>(bytes / durations); |
+ // Make sure the result is at least 1. |
+ return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1); |
} |
@@ -609,47 +611,77 @@ intptr_t GCTracer::FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() |
} |
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 static_cast<intptr_t>(bytes / durations); |
+ |
+double GCTracer::CombinedMarkCompactSpeedInBytesPerMillisecond() { |
+ if (combined_mark_compact_speed_cache_ > 0) |
+ return combined_mark_compact_speed_cache_; |
+ const double kEpsilon = 1; |
+ double speed1 = |
+ static_cast<double>(IncrementalMarkingSpeedInBytesPerMillisecond()); |
+ double speed2 = static_cast<double>( |
+ FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()); |
+ if (speed1 + speed2 < kEpsilon) { |
+ // No data for the incremental marking speed. |
+ // Return the non-incremental mark-compact speed. |
+ combined_mark_compact_speed_cache_ = |
+ static_cast<double>(MarkCompactSpeedInBytesPerMillisecond()); |
+ } else { |
+ // Combine the speed of incremental step and the speed of the final step. |
+ // 1 / (1 / speed1 + 1 / speed2) = speed1 * speed2 / (speed1 + speed2). |
+ combined_mark_compact_speed_cache_ = speed1 * speed2 / (speed1 + speed2); |
+ } |
+ return combined_mark_compact_speed_cache_; |
} |
-size_t GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond() const { |
+size_t 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) { |
+ 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; |
- |
- return static_cast<size_t>(bytes / durations + 0.5); |
+ // Make sure the result is at least 1. |
+ return Max<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1); |
} |
-size_t GCTracer::AllocationThroughputInBytesPerMillisecond( |
+size_t GCTracer::OldGenerationAllocationThroughputInBytesPerMillisecond( |
double time_ms) const { |
- size_t bytes = new_space_allocation_in_bytes_since_gc_ + |
- old_generation_allocation_in_bytes_since_gc_; |
+ size_t bytes = old_generation_allocation_in_bytes_since_gc_; |
double durations = allocation_duration_since_gc_; |
- AllocationEventBuffer::const_iterator iter = allocation_events_.begin(); |
+ AllocationEventBuffer::const_iterator iter = |
+ old_generation_allocation_events_.begin(); |
const size_t max_bytes = static_cast<size_t>(-1); |
- while (iter != allocation_events_.end() && bytes < max_bytes - bytes && |
- durations < time_ms) { |
+ 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<size_t>(static_cast<size_t>(bytes / durations + 0.5), 1); |
+} |
- return static_cast<size_t>(bytes / durations + 0.5); |
+ |
+size_t GCTracer::AllocationThroughputInBytesPerMillisecond( |
+ double time_ms) const { |
+ return NewSpaceAllocationThroughputInBytesPerMillisecond(time_ms) + |
+ OldGenerationAllocationThroughputInBytesPerMillisecond(time_ms); |
} |