LCOV - code coverage report
Current view: top level - test/unittests/heap - gc-tracer-unittest.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 232 262 88.5 %
Date: 2019-04-17 Functions: 40 59 67.8 %

          Line data    Source code
       1             : // Copyright 2014 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             : #include <cmath>
       6             : #include <limits>
       7             : 
       8             : #include "src/base/platform/platform.h"
       9             : #include "src/globals.h"
      10             : #include "src/heap/gc-tracer.h"
      11             : #include "src/isolate.h"
      12             : #include "test/unittests/test-utils.h"
      13             : #include "testing/gtest/include/gtest/gtest.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : using GCTracerTest = TestWithContext;
      19             : 
      20       15443 : TEST(GCTracer, AverageSpeed) {
      21             :   base::RingBuffer<BytesAndDuration> buffer;
      22           2 :   EXPECT_EQ(100 / 2,
      23           0 :             GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(100, 2), 0));
      24             :   buffer.Push(MakeBytesAndDuration(100, 8));
      25           2 :   EXPECT_EQ(100 / 2,
      26           0 :             GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(100, 2), 2));
      27           2 :   EXPECT_EQ(200 / 10,
      28           0 :             GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(100, 2), 3));
      29           1 :   const int max_speed = 1024 * MB;
      30             :   buffer.Reset();
      31             :   buffer.Push(MakeBytesAndDuration(max_speed, 0.5));
      32           2 :   EXPECT_EQ(max_speed,
      33           0 :             GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), 1));
      34           1 :   const int min_speed = 1;
      35             :   buffer.Reset();
      36             :   buffer.Push(MakeBytesAndDuration(1, 10000));
      37           2 :   EXPECT_EQ(min_speed,
      38           0 :             GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), 1));
      39             :   buffer.Reset();
      40             :   int sum = 0;
      41          11 :   for (int i = 0; i < buffer.kSize; i++) {
      42          10 :     sum += i + 1;
      43          10 :     buffer.Push(MakeBytesAndDuration(i + 1, 1));
      44             :   }
      45           2 :   EXPECT_EQ(
      46             :       sum * 1.0 / buffer.kSize,
      47           0 :       GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), buffer.kSize));
      48             :   buffer.Push(MakeBytesAndDuration(100, 1));
      49           2 :   EXPECT_EQ(
      50             :       (sum * 1.0 - 1 + 100) / buffer.kSize,
      51           0 :       GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), buffer.kSize));
      52           1 : }
      53             : 
      54             : namespace {
      55             : 
      56             : void SampleAndAddAllocaton(v8::internal::GCTracer* tracer, double time_ms,
      57             :                            size_t new_space_counter_bytes,
      58             :                            size_t old_generation_counter_bytes) {
      59             :   tracer->SampleAllocation(time_ms, new_space_counter_bytes,
      60          12 :                            old_generation_counter_bytes);
      61          12 :   tracer->AddAllocation(time_ms);
      62             : }
      63             : 
      64             : }  // namespace
      65             : 
      66       15444 : TEST_F(GCTracerTest, AllocationThroughput) {
      67             :   GCTracer* tracer = i_isolate()->heap()->tracer();
      68           1 :   tracer->ResetForTesting();
      69             : 
      70             :   int time1 = 100;
      71             :   size_t counter1 = 1000;
      72             :   // First sample creates baseline but is not part of the recorded samples.
      73           1 :   tracer->SampleAllocation(time1, counter1, counter1);
      74             :   SampleAndAddAllocaton(tracer, time1, counter1, counter1);
      75             :   int time2 = 200;
      76             :   size_t counter2 = 2000;
      77             :   SampleAndAddAllocaton(tracer, time2, counter2, counter2);
      78             :   // Will only consider the current sample.
      79             :   size_t throughput = static_cast<size_t>(
      80           1 :       tracer->AllocationThroughputInBytesPerMillisecond(100));
      81           2 :   EXPECT_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput);
      82             :   int time3 = 1000;
      83             :   size_t counter3 = 30000;
      84             :   SampleAndAddAllocaton(tracer, time3, counter3, counter3);
      85             :   // Considers last 2 samples.
      86           1 :   throughput = tracer->AllocationThroughputInBytesPerMillisecond(801);
      87           2 :   EXPECT_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput);
      88           1 : }
      89             : 
      90       15444 : TEST_F(GCTracerTest, NewSpaceAllocationThroughput) {
      91             :   GCTracer* tracer = i_isolate()->heap()->tracer();
      92           1 :   tracer->ResetForTesting();
      93             : 
      94             :   int time1 = 100;
      95             :   size_t counter1 = 1000;
      96             :   SampleAndAddAllocaton(tracer, time1, counter1, 0);
      97             :   int time2 = 200;
      98             :   size_t counter2 = 2000;
      99             :   SampleAndAddAllocaton(tracer, time2, counter2, 0);
     100             :   size_t throughput =
     101           1 :       tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
     102           2 :   EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
     103             :   int time3 = 1000;
     104             :   size_t counter3 = 30000;
     105             :   SampleAndAddAllocaton(tracer, time3, counter3, 0);
     106           1 :   throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
     107           2 :   EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
     108           1 : }
     109             : 
     110       15444 : TEST_F(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime) {
     111             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     112           1 :   tracer->ResetForTesting();
     113             : 
     114             :   int time1 = 100;
     115             :   size_t counter1 = 1000;
     116             :   // First sample creates baseline but is not part of the recorded samples.
     117             :   SampleAndAddAllocaton(tracer, time1, counter1, 0);
     118             :   int time2 = 200;
     119             :   size_t counter2 = 2000;
     120             :   SampleAndAddAllocaton(tracer, time2, counter2, 0);
     121             :   // Will only consider the current sample.
     122             :   size_t throughput =
     123           1 :       tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
     124           2 :   EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
     125             :   int time3 = 1000;
     126             :   size_t counter3 = 30000;
     127             :   SampleAndAddAllocaton(tracer, time3, counter3, 0);
     128             :   // Considers last 2 samples.
     129           1 :   throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(801);
     130           2 :   EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
     131           1 : }
     132             : 
     133       15444 : TEST_F(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime) {
     134             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     135           1 :   tracer->ResetForTesting();
     136             : 
     137             :   int time1 = 100;
     138             :   size_t counter1 = 1000;
     139             :   // First sample creates baseline but is not part of the recorded samples.
     140             :   SampleAndAddAllocaton(tracer, time1, 0, counter1);
     141             :   int time2 = 200;
     142             :   size_t counter2 = 2000;
     143             :   SampleAndAddAllocaton(tracer, time2, 0, counter2);
     144             :   // Will only consider the current sample.
     145             :   size_t throughput = static_cast<size_t>(
     146           1 :       tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100));
     147           2 :   EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
     148             :   int time3 = 1000;
     149             :   size_t counter3 = 30000;
     150             :   SampleAndAddAllocaton(tracer, time3, 0, counter3);
     151             :   // Considers last 2 samples.
     152             :   throughput = static_cast<size_t>(
     153           1 :       tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(801));
     154           2 :   EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
     155           1 : }
     156             : 
     157       15444 : TEST_F(GCTracerTest, RegularScope) {
     158             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     159           1 :   tracer->ResetForTesting();
     160             : 
     161           1 :   EXPECT_DOUBLE_EQ(0.0, tracer->current_.scopes[GCTracer::Scope::MC_MARK]);
     162             :   // Sample not added because it's not within a started tracer.
     163             :   tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100);
     164             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     165           1 :                 "collector unittest");
     166             :   tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100);
     167           1 :   tracer->Stop(MARK_COMPACTOR);
     168           1 :   EXPECT_DOUBLE_EQ(100.0, tracer->current_.scopes[GCTracer::Scope::MC_MARK]);
     169           1 : }
     170             : 
     171       15444 : TEST_F(GCTracerTest, IncrementalScope) {
     172             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     173           1 :   tracer->ResetForTesting();
     174             : 
     175           1 :   EXPECT_DOUBLE_EQ(
     176           0 :       0.0, tracer->current_.scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]);
     177             :   // Sample is added because its ScopeId is listed as incremental sample.
     178             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100);
     179             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     180           1 :                 "collector unittest");
     181             :   // Switch to incremental MC to enable writing back incremental scopes.
     182           1 :   tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
     183             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100);
     184           1 :   tracer->Stop(MARK_COMPACTOR);
     185           1 :   EXPECT_DOUBLE_EQ(
     186           0 :       200.0, tracer->current_.scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]);
     187           1 : }
     188             : 
     189       15444 : TEST_F(GCTracerTest, IncrementalMarkingDetails) {
     190             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     191           1 :   tracer->ResetForTesting();
     192             : 
     193             :   // Round 1.
     194             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 50);
     195             :   // Scavenger has no impact on incremental marking details.
     196             :   tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
     197           1 :                 "collector unittest");
     198           1 :   tracer->Stop(SCAVENGER);
     199             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     200           1 :                 "collector unittest");
     201             :   // Switch to incremental MC to enable writing back incremental scopes.
     202           1 :   tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
     203             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100);
     204           1 :   tracer->Stop(MARK_COMPACTOR);
     205           1 :   EXPECT_DOUBLE_EQ(
     206             :       100,
     207             :       tracer->current_
     208             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     209           0 :           .longest_step);
     210           2 :   EXPECT_EQ(
     211             :       2,
     212             :       tracer->current_
     213             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     214           0 :           .steps);
     215           1 :   EXPECT_DOUBLE_EQ(
     216             :       150,
     217             :       tracer->current_
     218             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     219           0 :           .duration);
     220             : 
     221             :   // Round 2. Numbers should be reset.
     222             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 13);
     223             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 15);
     224             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     225           1 :                 "collector unittest");
     226             :   // Switch to incremental MC to enable writing back incremental scopes.
     227           1 :   tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
     228             :   tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 122);
     229           1 :   tracer->Stop(MARK_COMPACTOR);
     230           1 :   EXPECT_DOUBLE_EQ(
     231             :       122,
     232             :       tracer->current_
     233             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     234           0 :           .longest_step);
     235           2 :   EXPECT_EQ(
     236             :       3,
     237             :       tracer->current_
     238             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     239           0 :           .steps);
     240           1 :   EXPECT_DOUBLE_EQ(
     241             :       150,
     242             :       tracer->current_
     243             :           .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     244           0 :           .duration);
     245           1 : }
     246             : 
     247       15444 : TEST_F(GCTracerTest, IncrementalMarkingSpeed) {
     248             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     249           1 :   tracer->ResetForTesting();
     250             : 
     251             :   // Round 1.
     252             :   // 1000000 bytes in 100ms.
     253           1 :   tracer->AddIncrementalMarkingStep(100, 1000000);
     254           2 :   EXPECT_EQ(1000000 / 100,
     255           0 :             tracer->IncrementalMarkingSpeedInBytesPerMillisecond());
     256             :   // 1000000 bytes in 100ms.
     257           1 :   tracer->AddIncrementalMarkingStep(100, 1000000);
     258           2 :   EXPECT_EQ(1000000 / 100,
     259           0 :             tracer->IncrementalMarkingSpeedInBytesPerMillisecond());
     260             :   // Scavenger has no impact on incremental marking details.
     261             :   tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
     262           1 :                 "collector unittest");
     263           1 :   tracer->Stop(SCAVENGER);
     264             :   // 1000000 bytes in 100ms.
     265           1 :   tracer->AddIncrementalMarkingStep(100, 1000000);
     266           2 :   EXPECT_EQ(300, tracer->incremental_marking_duration_);
     267           2 :   EXPECT_EQ(3000000u, tracer->incremental_marking_bytes_);
     268           2 :   EXPECT_EQ(1000000 / 100,
     269           0 :             tracer->IncrementalMarkingSpeedInBytesPerMillisecond());
     270             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     271           1 :                 "collector unittest");
     272             :   // Switch to incremental MC.
     273           1 :   tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
     274             :   // 1000000 bytes in 100ms.
     275           1 :   tracer->AddIncrementalMarkingStep(100, 1000000);
     276           2 :   EXPECT_EQ(400, tracer->incremental_marking_duration_);
     277           2 :   EXPECT_EQ(4000000u, tracer->incremental_marking_bytes_);
     278           1 :   tracer->Stop(MARK_COMPACTOR);
     279           2 :   EXPECT_EQ(400, tracer->current_.incremental_marking_duration);
     280           2 :   EXPECT_EQ(4000000u, tracer->current_.incremental_marking_bytes);
     281           2 :   EXPECT_EQ(0, tracer->incremental_marking_duration_);
     282           2 :   EXPECT_EQ(0u, tracer->incremental_marking_bytes_);
     283           2 :   EXPECT_EQ(1000000 / 100,
     284           0 :             tracer->IncrementalMarkingSpeedInBytesPerMillisecond());
     285             : 
     286             :   // Round 2.
     287           1 :   tracer->AddIncrementalMarkingStep(2000, 1000);
     288             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     289           1 :                 "collector unittest");
     290             :   // Switch to incremental MC.
     291           1 :   tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
     292           1 :   tracer->Stop(MARK_COMPACTOR);
     293           1 :   EXPECT_DOUBLE_EQ((4000000.0 / 400 + 1000.0 / 2000) / 2,
     294             :                    static_cast<double>(
     295           0 :                        tracer->IncrementalMarkingSpeedInBytesPerMillisecond()));
     296           1 : }
     297             : 
     298       15444 : TEST_F(GCTracerTest, MutatorUtilization) {
     299             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     300           1 :   tracer->ResetForTesting();
     301             : 
     302             :   // Mark-compact #1 ended at 200ms and took 100ms.
     303           1 :   tracer->RecordMutatorUtilization(200, 100);
     304             :   // Avarage mark-compact time = 0ms.
     305             :   // Avarage mutator time = 0ms.
     306           1 :   EXPECT_DOUBLE_EQ(1.0, tracer->CurrentMarkCompactMutatorUtilization());
     307           1 :   EXPECT_DOUBLE_EQ(1.0, tracer->AverageMarkCompactMutatorUtilization());
     308             : 
     309             :   // Mark-compact #2 ended at 400ms and took 100ms.
     310           1 :   tracer->RecordMutatorUtilization(400, 100);
     311             :   // The first mark-compactor is ignored.
     312             :   // Avarage mark-compact time = 100ms.
     313             :   // Avarage mutator time = 100ms.
     314           1 :   EXPECT_DOUBLE_EQ(0.5, tracer->CurrentMarkCompactMutatorUtilization());
     315           1 :   EXPECT_DOUBLE_EQ(0.5, tracer->AverageMarkCompactMutatorUtilization());
     316             : 
     317             :   // Mark-compact #3 ended at 600ms and took 200ms.
     318           1 :   tracer->RecordMutatorUtilization(600, 200);
     319             :   // Avarage mark-compact time = 100ms * 0.5 + 200ms * 0.5.
     320             :   // Avarage mutator time = 100ms * 0.5 + 0ms * 0.5.
     321           1 :   EXPECT_DOUBLE_EQ(0.0, tracer->CurrentMarkCompactMutatorUtilization());
     322           1 :   EXPECT_DOUBLE_EQ(50.0 / 200.0,
     323           0 :                    tracer->AverageMarkCompactMutatorUtilization());
     324             : 
     325             :   // Mark-compact #4 ended at 800ms and took 0ms.
     326           1 :   tracer->RecordMutatorUtilization(800, 0);
     327             :   // Avarage mark-compact time = 150ms * 0.5 + 0ms * 0.5.
     328             :   // Avarage mutator time = 50ms * 0.5 + 200ms * 0.5.
     329           1 :   EXPECT_DOUBLE_EQ(1.0, tracer->CurrentMarkCompactMutatorUtilization());
     330           1 :   EXPECT_DOUBLE_EQ(125.0 / 200.0,
     331           0 :                    tracer->AverageMarkCompactMutatorUtilization());
     332           1 : }
     333             : 
     334       15444 : TEST_F(GCTracerTest, BackgroundScavengerScope) {
     335             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     336           1 :   tracer->ResetForTesting();
     337             :   tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
     338           1 :                 "collector unittest");
     339             :   tracer->AddBackgroundScopeSample(
     340             :       GCTracer::BackgroundScope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL, 10,
     341           1 :       nullptr);
     342             :   tracer->AddBackgroundScopeSample(
     343             :       GCTracer::BackgroundScope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL, 1,
     344           1 :       nullptr);
     345           1 :   tracer->Stop(SCAVENGER);
     346           1 :   EXPECT_DOUBLE_EQ(
     347             :       11, tracer->current_
     348           0 :               .scopes[GCTracer::Scope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL]);
     349           1 : }
     350             : 
     351       15444 : TEST_F(GCTracerTest, BackgroundMinorMCScope) {
     352             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     353           1 :   tracer->ResetForTesting();
     354             :   tracer->Start(MINOR_MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     355           1 :                 "collector unittest");
     356             :   tracer->AddBackgroundScopeSample(
     357           1 :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_MARKING, 10, nullptr);
     358             :   tracer->AddBackgroundScopeSample(
     359           1 :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_MARKING, 1, nullptr);
     360             :   tracer->AddBackgroundScopeSample(
     361             :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_COPY, 20,
     362           1 :       nullptr);
     363             :   tracer->AddBackgroundScopeSample(
     364           1 :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_COPY, 2, nullptr);
     365             :   tracer->AddBackgroundScopeSample(
     366             :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
     367           1 :       30, nullptr);
     368             :   tracer->AddBackgroundScopeSample(
     369             :       GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
     370           1 :       3, nullptr);
     371           1 :   tracer->Stop(MINOR_MARK_COMPACTOR);
     372           1 :   EXPECT_DOUBLE_EQ(
     373             :       11,
     374           0 :       tracer->current_.scopes[GCTracer::Scope::MINOR_MC_BACKGROUND_MARKING]);
     375           1 :   EXPECT_DOUBLE_EQ(
     376             :       22, tracer->current_
     377           0 :               .scopes[GCTracer::Scope::MINOR_MC_BACKGROUND_EVACUATE_COPY]);
     378           1 :   EXPECT_DOUBLE_EQ(
     379             :       33, tracer->current_.scopes
     380           0 :               [GCTracer::Scope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS]);
     381           1 : }
     382             : 
     383       15444 : TEST_F(GCTracerTest, BackgroundMajorMCScope) {
     384             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     385           1 :   tracer->ResetForTesting();
     386             :   tracer->AddBackgroundScopeSample(
     387           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 100, nullptr);
     388             :   tracer->AddBackgroundScopeSample(
     389           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 200, nullptr);
     390             :   tracer->AddBackgroundScopeSample(
     391           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 10, nullptr);
     392             :   // Scavenger should not affect the major mark-compact scopes.
     393             :   tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
     394           1 :                 "collector unittest");
     395           1 :   tracer->Stop(SCAVENGER);
     396             :   tracer->AddBackgroundScopeSample(
     397           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 20, nullptr);
     398             :   tracer->AddBackgroundScopeSample(
     399           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 1, nullptr);
     400             :   tracer->AddBackgroundScopeSample(
     401           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 2, nullptr);
     402             :   tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
     403           1 :                 "collector unittest");
     404             :   tracer->AddBackgroundScopeSample(
     405           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_COPY, 30, nullptr);
     406             :   tracer->AddBackgroundScopeSample(
     407           1 :       GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_COPY, 3, nullptr);
     408             :   tracer->AddBackgroundScopeSample(
     409             :       GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS, 40,
     410           1 :       nullptr);
     411             :   tracer->AddBackgroundScopeSample(
     412             :       GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS, 4,
     413           1 :       nullptr);
     414           1 :   tracer->Stop(MARK_COMPACTOR);
     415           1 :   EXPECT_DOUBLE_EQ(
     416           0 :       111, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_MARKING]);
     417           1 :   EXPECT_DOUBLE_EQ(
     418           0 :       222, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_SWEEPING]);
     419           1 :   EXPECT_DOUBLE_EQ(
     420             :       33,
     421           0 :       tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_EVACUATE_COPY]);
     422           1 :   EXPECT_DOUBLE_EQ(
     423             :       44, tracer->current_
     424           0 :               .scopes[GCTracer::Scope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS]);
     425           1 : }
     426             : 
     427           1 : class ThreadWithBackgroundScope final : public base::Thread {
     428             :  public:
     429             :   explicit ThreadWithBackgroundScope(GCTracer* tracer)
     430           2 :       : Thread(Options("ThreadWithBackgroundScope")), tracer_(tracer) {}
     431           2 :   void Run() override {
     432             :     GCTracer::BackgroundScope scope(
     433           2 :         tracer_, GCTracer::BackgroundScope::MC_BACKGROUND_MARKING);
     434           2 :   }
     435             : 
     436             :  private:
     437             :   GCTracer* tracer_;
     438             : };
     439             : 
     440       15444 : TEST_F(GCTracerTest, MultithreadedBackgroundScope) {
     441             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     442             :   ThreadWithBackgroundScope thread1(tracer);
     443             :   ThreadWithBackgroundScope thread2(tracer);
     444           1 :   tracer->ResetForTesting();
     445           1 :   thread1.Start();
     446           1 :   thread2.Start();
     447           1 :   tracer->FetchBackgroundMarkCompactCounters();
     448           1 :   thread1.Join();
     449           1 :   thread2.Join();
     450           1 :   tracer->FetchBackgroundMarkCompactCounters();
     451           1 :   EXPECT_LE(0, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_MARKING]);
     452           1 : }
     453             : 
     454         354 : class GcHistogram {
     455             :  public:
     456         354 :   static void* CreateHistogram(const char* name, int min, int max,
     457             :                                size_t buckets) {
     458         708 :     histograms_[name] = std::unique_ptr<GcHistogram>(new GcHistogram());
     459         708 :     return histograms_[name].get();
     460             :   }
     461             : 
     462          11 :   static void AddHistogramSample(void* histogram, int sample) {
     463          11 :     if (histograms_.empty()) return;
     464          11 :     static_cast<GcHistogram*>(histogram)->samples_.push_back(sample);
     465             :   }
     466             : 
     467          20 :   static GcHistogram* Get(const char* name) { return histograms_[name].get(); }
     468             : 
     469             :   static void CleanUp() { histograms_.clear(); }
     470             : 
     471             :   int Total() const {
     472             :     int result = 0;
     473          20 :     for (int i : samples_) {
     474          10 :       result += i;
     475             :     }
     476             :     return result;
     477             :   }
     478             : 
     479             :   int Count() const { return static_cast<int>(samples_.size()); }
     480             : 
     481             :  private:
     482             :   std::vector<int> samples_;
     483             :   static std::map<std::string, std::unique_ptr<GcHistogram>> histograms_;
     484             : };
     485             : 
     486        3088 : std::map<std::string, std::unique_ptr<GcHistogram>> GcHistogram::histograms_ =
     487             :     std::map<std::string, std::unique_ptr<GcHistogram>>();
     488             : 
     489       15444 : TEST_F(GCTracerTest, RecordMarkCompactHistograms) {
     490           1 :   if (FLAG_stress_incremental_marking) return;
     491           1 :   isolate()->SetCreateHistogramFunction(&GcHistogram::CreateHistogram);
     492           1 :   isolate()->SetAddHistogramSampleFunction(&GcHistogram::AddHistogramSample);
     493             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     494           1 :   tracer->ResetForTesting();
     495           1 :   tracer->current_.scopes[GCTracer::Scope::MC_CLEAR] = 1;
     496           1 :   tracer->current_.scopes[GCTracer::Scope::MC_EPILOGUE] = 2;
     497           1 :   tracer->current_.scopes[GCTracer::Scope::MC_EVACUATE] = 3;
     498           1 :   tracer->current_.scopes[GCTracer::Scope::MC_FINISH] = 4;
     499           1 :   tracer->current_.scopes[GCTracer::Scope::MC_MARK] = 5;
     500           1 :   tracer->current_.scopes[GCTracer::Scope::MC_PROLOGUE] = 6;
     501           1 :   tracer->current_.scopes[GCTracer::Scope::MC_SWEEP] = 7;
     502           1 :   tracer->RecordGCPhasesHistograms(i_isolate()->counters()->gc_finalize());
     503           3 :   EXPECT_EQ(1, GcHistogram::Get("V8.GCFinalizeMC.Clear")->Total());
     504           3 :   EXPECT_EQ(2, GcHistogram::Get("V8.GCFinalizeMC.Epilogue")->Total());
     505           3 :   EXPECT_EQ(3, GcHistogram::Get("V8.GCFinalizeMC.Evacuate")->Total());
     506           3 :   EXPECT_EQ(4, GcHistogram::Get("V8.GCFinalizeMC.Finish")->Total());
     507           3 :   EXPECT_EQ(5, GcHistogram::Get("V8.GCFinalizeMC.Mark")->Total());
     508           3 :   EXPECT_EQ(6, GcHistogram::Get("V8.GCFinalizeMC.Prologue")->Total());
     509           3 :   EXPECT_EQ(7, GcHistogram::Get("V8.GCFinalizeMC.Sweep")->Total());
     510             :   GcHistogram::CleanUp();
     511             : }
     512             : 
     513       15444 : TEST_F(GCTracerTest, RecordScavengerHistograms) {
     514           1 :   if (FLAG_stress_incremental_marking) return;
     515           1 :   isolate()->SetCreateHistogramFunction(&GcHistogram::CreateHistogram);
     516           1 :   isolate()->SetAddHistogramSampleFunction(&GcHistogram::AddHistogramSample);
     517             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     518           1 :   tracer->ResetForTesting();
     519           1 :   tracer->current_.scopes[GCTracer::Scope::SCAVENGER_SCAVENGE_ROOTS] = 1;
     520           1 :   tracer->current_.scopes[GCTracer::Scope::SCAVENGER_SCAVENGE_PARALLEL] = 2;
     521           1 :   tracer->RecordGCPhasesHistograms(i_isolate()->counters()->gc_scavenger());
     522           3 :   EXPECT_EQ(1, GcHistogram::Get("V8.GCScavenger.ScavengeRoots")->Total());
     523           3 :   EXPECT_EQ(2, GcHistogram::Get("V8.GCScavenger.ScavengeMain")->Total());
     524             :   GcHistogram::CleanUp();
     525             : }
     526             : 
     527       15444 : TEST_F(GCTracerTest, RecordGCSumHistograms) {
     528           1 :   if (FLAG_stress_incremental_marking) return;
     529           1 :   isolate()->SetCreateHistogramFunction(&GcHistogram::CreateHistogram);
     530           1 :   isolate()->SetAddHistogramSampleFunction(&GcHistogram::AddHistogramSample);
     531             :   GCTracer* tracer = i_isolate()->heap()->tracer();
     532           1 :   tracer->ResetForTesting();
     533             :   tracer->current_
     534             :       .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_START]
     535           1 :       .duration = 1;
     536             :   tracer->current_
     537             :       .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_SWEEPING]
     538           1 :       .duration = 2;
     539           1 :   tracer->AddIncrementalMarkingStep(3.0, 1024);
     540             :   tracer->current_
     541             :       .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
     542           1 :       .duration = 4;
     543             :   const double atomic_pause_duration = 5.0;
     544           1 :   tracer->RecordGCSumCounters(atomic_pause_duration);
     545           3 :   EXPECT_EQ(15, GcHistogram::Get("V8.GCMarkCompactor")->Total());
     546             :   GcHistogram::CleanUp();
     547             : }
     548             : 
     549             : }  // namespace internal
     550        9264 : }  // namespace v8

Generated by: LCOV version 1.10