| Index: components/tracing/test/heap_profiler_perftest.cc
|
| diff --git a/components/tracing/test/heap_profiler_perftest.cc b/components/tracing/test/heap_profiler_perftest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d776e4ff6d18c5d11d74331c812c6ecf63e59408
|
| --- /dev/null
|
| +++ b/components/tracing/test/heap_profiler_perftest.cc
|
| @@ -0,0 +1,159 @@
|
| +// Copyright 2017 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 <algorithm>
|
| +#include <iterator>
|
| +#include <vector>
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/time/time.h"
|
| +#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
|
| +#include "base/trace_event/heap_profiler_string_deduplicator.h"
|
| +#include "base/trace_event/trace_event_argument.h"
|
| +#include "perf_test_helpers.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace tracing {
|
| +namespace {
|
| +
|
| +using namespace base::trace_event;
|
| +
|
| +class HeapProfilerPerfTest : public testing::Test {
|
| + protected:
|
| + struct StackFrameVariations {
|
| + size_t skew;
|
| + std::vector<StackFrame> values;
|
| + };
|
| + using BacktraceVariations = std::vector<StackFrameVariations>;
|
| +
|
| + BacktraceVariations GetRandomBacktraceVariations() {
|
| + struct VariationSpec {
|
| + size_t value_count; // number of unique frames
|
| + size_t skew; // see GetSkewedRandom()
|
| + size_t length; // number of backtrace levels covered
|
| + };
|
| + static const VariationSpec specs[] = {
|
| + // These values give realistic insertion pattern with 60% hit count.
|
| + {100, 90, Backtrace::kMaxFrameCount - 5},
|
| + {10, 5, 5}};
|
| +
|
| + BacktraceVariations backtrace_variations;
|
| + const VariationSpec* spec = std::begin(specs);
|
| + size_t spec_end_depth = spec->length;
|
| + for (size_t depth = 0; depth != Backtrace::kMaxFrameCount; ++depth) {
|
| + if (depth == spec_end_depth) {
|
| + if (spec != std::end(specs) - 1) {
|
| + spec++;
|
| + spec_end_depth = depth + spec->length;
|
| + } else {
|
| + spec_end_depth = Backtrace::kMaxFrameCount;
|
| + }
|
| + }
|
| + backtrace_variations.push_back({spec->skew});
|
| + auto& frame_variations = backtrace_variations.back();
|
| + for (size_t v = 0; v != spec->value_count; ++v) {
|
| + uintptr_t pc = static_cast<uintptr_t>(GetRandom64());
|
| + frame_variations.values.push_back(
|
| + StackFrame::FromProgramCounter(reinterpret_cast<void*>(pc)));
|
| + }
|
| + }
|
| +
|
| + return backtrace_variations;
|
| + }
|
| +
|
| + size_t InsertRandomBacktraces(StackFrameDeduplicator* deduplicator,
|
| + const BacktraceVariations& backtrace_variations,
|
| + size_t max_frame_count) {
|
| + size_t insert_count = 0;
|
| + while (true) {
|
| + insert_count++;
|
| + Backtrace backtrace = RandomBacktrace(backtrace_variations);
|
| + deduplicator->Insert(backtrace.frames,
|
| + backtrace.frames + backtrace.frame_count);
|
| + size_t frame_count = deduplicator->end() - deduplicator->begin();
|
| + if (frame_count > max_frame_count) {
|
| + break;
|
| + }
|
| + }
|
| + return insert_count;
|
| + }
|
| +
|
| + private:
|
| + uint32_t GetRandom32() {
|
| + random_seed_ = random_seed_ * 1664525 + 1013904223;
|
| + return random_seed_;
|
| + }
|
| +
|
| + uint64_t GetRandom64() {
|
| + uint64_t rnd = GetRandom32();
|
| + return (rnd << 32) | GetRandom32();
|
| + }
|
| +
|
| + // Returns random number in range [0, max).
|
| + uint32_t GetRandom32(uint32_t max) {
|
| + uint64_t rnd = GetRandom32();
|
| + return static_cast<uint32_t>((rnd * max) >> 32);
|
| + }
|
| +
|
| + // In 1/skew cases returns random value in range [0, max), in all
|
| + // other cases returns value in range [0, max/skew). The average value
|
| + // ends up being (2*skew - 1) / (2*skew^2) * max.
|
| + uint32_t GetSkewedRandom(uint32_t max, uint32_t skew) {
|
| + if (GetRandom32(skew) != (skew - 1)) {
|
| + max /= skew;
|
| + }
|
| + return GetRandom32(max);
|
| + }
|
| +
|
| + Backtrace RandomBacktrace(const BacktraceVariations& backtrace_variations) {
|
| + Backtrace backtrace;
|
| + backtrace.frame_count = Backtrace::kMaxFrameCount;
|
| + for (size_t depth = 0; depth != backtrace.frame_count; ++depth) {
|
| + const auto& frame_variations = backtrace_variations[depth];
|
| + size_t value_index =
|
| + GetSkewedRandom(static_cast<uint32_t>(frame_variations.values.size()),
|
| + static_cast<uint32_t>(frame_variations.skew));
|
| + backtrace.frames[depth] = frame_variations.values[value_index];
|
| + }
|
| + return backtrace;
|
| + }
|
| +
|
| + private:
|
| + uint32_t random_seed_ = 777;
|
| +};
|
| +
|
| +TEST_F(HeapProfilerPerfTest, DeduplicateStackFrames) {
|
| + StringDeduplicator string_deduplicator;
|
| + StackFrameDeduplicator deduplicator(&string_deduplicator);
|
| +
|
| + auto variations = GetRandomBacktraceVariations();
|
| +
|
| + {
|
| + ScopedStopwatch stopwatch("time_to_insert");
|
| + InsertRandomBacktraces(&deduplicator, variations, 1000000);
|
| + }
|
| +}
|
| +
|
| +TEST_F(HeapProfilerPerfTest, AppendStackFramesAsTraceFormat) {
|
| + StringDeduplicator string_deduplicator;
|
| + StackFrameDeduplicator deduplicator(&string_deduplicator);
|
| +
|
| + auto variations = GetRandomBacktraceVariations();
|
| + InsertRandomBacktraces(&deduplicator, variations, 1000000);
|
| +
|
| + auto traced_value = base::MakeUnique<TracedValue>();
|
| + traced_value->BeginArray("nodes");
|
| + deduplicator.SerializeIncrementally(traced_value.get());
|
| + traced_value->EndArray();
|
| +
|
| + {
|
| + ScopedStopwatch stopwatch("time_to_append");
|
| + std::string json;
|
| + traced_value->AppendAsTraceFormat(&json);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace tracing
|
|
|