blob: bc61502cb760e76f71752b2ee6226ce6af155e2f [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/callback.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_result_reporter.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
namespace blink {
class WriteBarrierPerfTest : public TestSupportingGC {};
namespace {
constexpr char kMetricPrefixWriteBarrier[] = "WriteBarrier.";
constexpr char kMetricWritesDuringGcRunsPerS[] = "writes_during_gc";
constexpr char kMetricWritesOutsideGcRunsPerS[] = "writes_outside_gc";
constexpr char kMetricRelativeSpeedDifferenceUnitless[] =
"relative_speed_difference";
perf_test::PerfResultReporter SetUpReporter(const std::string& story_name) {
perf_test::PerfResultReporter reporter(kMetricPrefixWriteBarrier, story_name);
reporter.RegisterImportantMetric(kMetricWritesDuringGcRunsPerS, "runs/s");
reporter.RegisterImportantMetric(kMetricWritesOutsideGcRunsPerS, "runs/s");
reporter.RegisterImportantMetric(kMetricRelativeSpeedDifferenceUnitless,
"unitless");
return reporter;
}
class PerfDummyObject : public GarbageCollected<PerfDummyObject> {
public:
PerfDummyObject() = default;
virtual void Trace(Visitor*) const {}
};
base::TimeDelta TimedRun(base::RepeatingCallback<void()> callback) {
const base::TimeTicks start = base::TimeTicks::Now();
callback.Run();
return base::TimeTicks::Now() - start;
}
} // namespace
TEST_F(WriteBarrierPerfTest, MemberWritePerformance) {
// Setup.
constexpr wtf_size_t kNumElements = 100000;
Persistent<HeapVector<Member<PerfDummyObject>>> holder(
MakeGarbageCollected<HeapVector<Member<PerfDummyObject>>>());
for (wtf_size_t i = 0; i < kNumElements; ++i) {
holder->push_back(MakeGarbageCollected<PerfDummyObject>());
}
PreciselyCollectGarbage();
// Benchmark.
base::RepeatingCallback<void()> benchmark = base::BindRepeating(
[](const Persistent<HeapVector<Member<PerfDummyObject>>>& holder) {
for (wtf_size_t i = 0; i < kNumElements / 2; ++i) {
(*holder)[i].Swap((*holder)[kNumElements / 2 + i]);
}
},
holder);
// During GC.
IncrementalMarkingTestDriver driver(ThreadState::Current());
driver.Start();
base::TimeDelta during_gc_duration = TimedRun(benchmark);
driver.FinishSteps();
PreciselyCollectGarbage();
// Outside GC.
base::TimeDelta outside_gc_duration = TimedRun(benchmark);
// Cleanup.
holder.Clear();
PreciselyCollectGarbage();
// Reporting.
auto reporter = SetUpReporter("member_write_performance");
reporter.AddResult(kMetricWritesDuringGcRunsPerS,
kNumElements / during_gc_duration.InSecondsF());
reporter.AddResult(kMetricWritesOutsideGcRunsPerS,
kNumElements / outside_gc_duration.InSecondsF());
reporter.AddResult(kMetricRelativeSpeedDifferenceUnitless,
during_gc_duration / outside_gc_duration);
}
} // namespace blink