| Index: test/unittests/heap/gc-tracer-unittest.cc | 
| diff --git a/test/unittests/heap/gc-tracer-unittest.cc b/test/unittests/heap/gc-tracer-unittest.cc | 
| index 2bf4d037d3ba4eaaee8975458e3d7224c54ec992..97975d488bbfe5bb8720b080d1dc57289656630a 100644 | 
| --- a/test/unittests/heap/gc-tracer-unittest.cc | 
| +++ b/test/unittests/heap/gc-tracer-unittest.cc | 
| @@ -5,12 +5,17 @@ | 
| #include <cmath> | 
| #include <limits> | 
|  | 
| +#include "src/globals.h" | 
| #include "src/heap/gc-tracer.h" | 
| +#include "src/isolate.h" | 
| +#include "test/unittests/test-utils.h" | 
| #include "testing/gtest/include/gtest/gtest.h" | 
|  | 
| namespace v8 { | 
| namespace internal { | 
|  | 
| +typedef TestWithContext GCTracerTest; | 
| + | 
| TEST(GCTracer, AverageSpeed) { | 
| RingBuffer<BytesAndDuration> buffer; | 
| EXPECT_EQ(100 / 2, | 
| @@ -45,5 +50,138 @@ TEST(GCTracer, AverageSpeed) { | 
| GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), buffer.kSize)); | 
| } | 
|  | 
| +namespace { | 
| + | 
| +void SampleAndAddAllocaton(v8::internal::GCTracer* tracer, double time_ms, | 
| +                           size_t new_space_counter_bytes, | 
| +                           size_t old_generation_counter_bytes) { | 
| +  tracer->SampleAllocation(time_ms, new_space_counter_bytes, | 
| +                           old_generation_counter_bytes); | 
| +  tracer->AddAllocation(time_ms); | 
| +} | 
| + | 
| +}  // namespace | 
| + | 
| +TEST_F(GCTracerTest, AllocationThroughput) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  int time1 = 100; | 
| +  size_t counter1 = 1000; | 
| +  // First sample creates baseline but is not part of the recorded samples. | 
| +  tracer->SampleAllocation(time1, counter1, counter1); | 
| +  SampleAndAddAllocaton(tracer, time1, counter1, counter1); | 
| +  int time2 = 200; | 
| +  size_t counter2 = 2000; | 
| +  SampleAndAddAllocaton(tracer, time2, counter2, counter2); | 
| +  // Will only consider the current sample. | 
| +  size_t throughput = static_cast<size_t>( | 
| +      tracer->AllocationThroughputInBytesPerMillisecond(100)); | 
| +  EXPECT_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput); | 
| +  int time3 = 1000; | 
| +  size_t counter3 = 30000; | 
| +  SampleAndAddAllocaton(tracer, time3, counter3, counter3); | 
| +  // Considers last 2 samples. | 
| +  throughput = tracer->AllocationThroughputInBytesPerMillisecond(801); | 
| +  EXPECT_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput); | 
| +} | 
| + | 
| +TEST_F(GCTracerTest, NewSpaceAllocationThroughput) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  int time1 = 100; | 
| +  size_t counter1 = 1000; | 
| +  SampleAndAddAllocaton(tracer, time1, counter1, 0); | 
| +  int time2 = 200; | 
| +  size_t counter2 = 2000; | 
| +  SampleAndAddAllocaton(tracer, time2, counter2, 0); | 
| +  size_t throughput = | 
| +      tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(); | 
| +  EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput); | 
| +  int time3 = 1000; | 
| +  size_t counter3 = 30000; | 
| +  SampleAndAddAllocaton(tracer, time3, counter3, 0); | 
| +  throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(); | 
| +  EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput); | 
| +} | 
| + | 
| +TEST_F(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  int time1 = 100; | 
| +  size_t counter1 = 1000; | 
| +  // First sample creates baseline but is not part of the recorded samples. | 
| +  SampleAndAddAllocaton(tracer, time1, counter1, 0); | 
| +  int time2 = 200; | 
| +  size_t counter2 = 2000; | 
| +  SampleAndAddAllocaton(tracer, time2, counter2, 0); | 
| +  // Will only consider the current sample. | 
| +  size_t throughput = | 
| +      tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100); | 
| +  EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput); | 
| +  int time3 = 1000; | 
| +  size_t counter3 = 30000; | 
| +  SampleAndAddAllocaton(tracer, time3, counter3, 0); | 
| +  // Considers last 2 samples. | 
| +  throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(801); | 
| +  EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput); | 
| +} | 
| + | 
| +TEST_F(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  int time1 = 100; | 
| +  size_t counter1 = 1000; | 
| +  // First sample creates baseline but is not part of the recorded samples. | 
| +  SampleAndAddAllocaton(tracer, time1, 0, counter1); | 
| +  int time2 = 200; | 
| +  size_t counter2 = 2000; | 
| +  SampleAndAddAllocaton(tracer, time2, 0, counter2); | 
| +  // Will only consider the current sample. | 
| +  size_t throughput = static_cast<size_t>( | 
| +      tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100)); | 
| +  EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput); | 
| +  int time3 = 1000; | 
| +  size_t counter3 = 30000; | 
| +  SampleAndAddAllocaton(tracer, time3, 0, counter3); | 
| +  // Considers last 2 samples. | 
| +  throughput = static_cast<size_t>( | 
| +      tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(801)); | 
| +  EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput); | 
| +} | 
| + | 
| +TEST_F(GCTracerTest, RegularScope) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  EXPECT_DOUBLE_EQ(0.0, tracer->current_.scopes[GCTracer::Scope::MC_MARK]); | 
| +  // Sample not added because it's not within a started tracer. | 
| +  tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100); | 
| +  tracer->Start(MARK_COMPACTOR, "gc unittest", "collector unittest"); | 
| +  tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100); | 
| +  tracer->Stop(MARK_COMPACTOR); | 
| +  EXPECT_DOUBLE_EQ(100.0, tracer->current_.scopes[GCTracer::Scope::MC_MARK]); | 
| +} | 
| + | 
| +TEST_F(GCTracerTest, IncrementalScope) { | 
| +  GCTracer* tracer = i_isolate()->heap()->tracer(); | 
| +  tracer->ResetForTesting(); | 
| + | 
| +  EXPECT_DOUBLE_EQ( | 
| +      0.0, tracer->current_.scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]); | 
| +  // Sample is added because its ScopeId is listed as incremental sample. | 
| +  tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100); | 
| +  tracer->Start(MARK_COMPACTOR, "gc unittest", "collector unittest"); | 
| +  // Switch to incremental MC to enable writing back incremental scopes. | 
| +  tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR; | 
| +  tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100); | 
| +  tracer->Stop(MARK_COMPACTOR); | 
| +  EXPECT_DOUBLE_EQ( | 
| +      200.0, tracer->current_.scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]); | 
| +} | 
| + | 
| }  // namespace internal | 
| }  // namespace v8 | 
|  |