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..58dc61703954bee1fbd3fd508d890fec31c7e1db |
--- /dev/null |
+++ b/components/tracing/test/heap_profiler_perftest.cc |
@@ -0,0 +1,158 @@ |
+// 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; |
Primiano Tucci (use gerrit)
2017/07/13 17:33:16
y not like rand()?
DmitrySkiba
2017/07/13 17:36:40
handwritten rand is best rand :)
But seriously, I
|
+ 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(frame_variations.values.size(), |
+ 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 |