blob: 8c3d2fb64fc7e03c00b942b6a10240ce6c63594a [file] [log] [blame]
Lalit Magantibfc3d3e2018-03-22 20:28:38 +00001// Copyright (C) 2018 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <gtest/gtest.h>
16#include <random>
17
18#include "benchmark/benchmark.h"
19#include "perfetto/base/time.h"
20#include "perfetto/trace/trace_packet.pb.h"
21#include "perfetto/trace/trace_packet.pbzero.h"
22#include "perfetto/traced/traced.h"
23#include "perfetto/tracing/core/trace_config.h"
24#include "perfetto/tracing/core/trace_packet.h"
25#include "src/base/test/test_task_runner.h"
26#include "test/fake_consumer.h"
27#include "test/task_runner_thread.h"
28#include "test/task_runner_thread_delegates.h"
29
30namespace perfetto {
31
Lalit Maganti131b6e52018-03-29 18:29:31 +010032namespace {
33
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000034// If we're building on Android and starting the daemons ourselves,
35// create the sockets in a world-writable location.
36#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
37 PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
38#define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
39#define TEST_CONSUMER_SOCK_NAME "/data/local/tmp/traced_consumer"
40#else
41#define TEST_PRODUCER_SOCK_NAME PERFETTO_PRODUCER_SOCK_NAME
42#define TEST_CONSUMER_SOCK_NAME PERFETTO_CONSUMER_SOCK_NAME
43#endif
44
Lalit Maganti131b6e52018-03-29 18:29:31 +010045bool IsBenchmarkFunctionalOnly() {
46 return getenv("BENCHMARK_FUNCTIONAL_TEST_ONLY") != nullptr;
47}
48
49void BenchmarkCommon(benchmark::State& state) {
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000050 base::TestTaskRunner task_runner;
51
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000052#if PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
53 TaskRunnerThread service_thread("perfetto.svc");
54 service_thread.Start(std::unique_ptr<ServiceDelegate>(
55 new ServiceDelegate(TEST_PRODUCER_SOCK_NAME, TEST_CONSUMER_SOCK_NAME)));
56#endif
57
58 TaskRunnerThread producer_thread("perfetto.prd");
59 auto on_producer_enabled = task_runner.CreateCheckpoint("producer.enabled");
60 auto posted_on_producer_enabled = [&task_runner, &on_producer_enabled] {
61 task_runner.PostTask(on_producer_enabled);
62 };
63 std::unique_ptr<FakeProducerDelegate> producer_delegate(
64 new FakeProducerDelegate(TEST_PRODUCER_SOCK_NAME,
Lalit Maganti131b6e52018-03-29 18:29:31 +010065 std::move(posted_on_producer_enabled)));
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000066 FakeProducerDelegate* producer_delegate_cached = producer_delegate.get();
67 producer_thread.Start(std::move(producer_delegate));
68
Lalit Maganti131b6e52018-03-29 18:29:31 +010069 // Once conneced, we can retrieve the inner producer.
70 FakeProducer* producer = producer_delegate_cached->producer();
71
Lalit Magantidd95ef92018-03-23 09:42:48 +000072 // Setup the TraceConfig for the consumer.
Lalit Magantidd95ef92018-03-23 09:42:48 +000073 TraceConfig trace_config;
74 trace_config.add_buffers()->set_size_kb(512);
75
76 // Create the buffer for ftrace.
77 auto* ds_config = trace_config.add_data_sources()->mutable_config();
78 ds_config->set_name("android.perfetto.FakeProducer");
79 ds_config->set_target_buffer(0);
80
81 // The parameters for the producer.
82 static constexpr uint32_t kRandomSeed = 42;
Lalit Maganti131b6e52018-03-29 18:29:31 +010083 size_t message_count = state.range(0);
84 size_t message_bytes = state.range(1);
85 size_t mb_per_s = state.range(2);
86
87 size_t messages_per_s = mb_per_s * 1024 * 1024 / message_bytes;
88 size_t time_for_messages_ms =
89 10000 + (messages_per_s == 0 ? 0 : message_count * 1000 / messages_per_s);
Lalit Magantidd95ef92018-03-23 09:42:48 +000090
91 // Setup the test to use a random number generator.
92 ds_config->mutable_for_testing()->set_seed(kRandomSeed);
93 ds_config->mutable_for_testing()->set_message_count(message_count);
Lalit Maganti131b6e52018-03-29 18:29:31 +010094 ds_config->mutable_for_testing()->set_message_size(message_bytes);
95 ds_config->mutable_for_testing()->set_max_messages_per_second(messages_per_s);
Lalit Magantidd95ef92018-03-23 09:42:48 +000096
Lalit Magantibfc3d3e2018-03-22 20:28:38 +000097 bool is_first_packet = true;
98 auto on_readback_complete = task_runner.CreateCheckpoint("readback.complete");
99 std::minstd_rand0 rnd_engine(kRandomSeed);
100 auto on_consumer_data = [&is_first_packet, &on_readback_complete,
101 &rnd_engine](std::vector<TracePacket> packets,
102 bool has_more) {
103 for (auto& packet : packets) {
104 ASSERT_TRUE(packet.Decode());
Lalit Maganti131b6e52018-03-29 18:29:31 +0100105 ASSERT_TRUE(packet->has_for_testing() || packet->has_clock_snapshot() ||
106 packet->has_trace_config());
107 if (packet->has_clock_snapshot() || packet->has_trace_config())
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000108 continue;
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000109 ASSERT_EQ(protos::TracePacket::kTrustedUid,
110 packet->optional_trusted_uid_case());
111 if (is_first_packet) {
112 rnd_engine = std::minstd_rand0(packet->for_testing().seq_value());
113 is_first_packet = false;
114 } else {
115 ASSERT_EQ(packet->for_testing().seq_value(), rnd_engine());
116 }
117 }
118
119 if (!has_more) {
120 is_first_packet = true;
121 on_readback_complete();
122 }
123 };
124
125 // Finally, make the consumer connect to the service.
126 auto on_connect = task_runner.CreateCheckpoint("consumer.connected");
127 FakeConsumer consumer(trace_config, std::move(on_connect),
128 std::move(on_consumer_data), &task_runner);
129 consumer.Connect(TEST_CONSUMER_SOCK_NAME);
130 task_runner.RunUntilCheckpoint("consumer.connected");
131
132 consumer.EnableTracing();
133 task_runner.RunUntilCheckpoint("producer.enabled");
134
135 uint64_t wall_start_ns = base::GetWallTimeNs().count();
Lalit Maganti131b6e52018-03-29 18:29:31 +0100136 uint64_t service_start_ns = service_thread.GetThreadCPUTimeNs();
137 uint64_t producer_start_ns = producer_thread.GetThreadCPUTimeNs();
Lalit Magantidd95ef92018-03-23 09:42:48 +0000138 uint64_t iterations = 0;
139 for (auto _ : state) {
140 auto cname = "produced.and.committed." + std::to_string(iterations++);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000141 auto on_produced_and_committed = task_runner.CreateCheckpoint(cname);
142 auto posted_on_produced_and_committed = [&task_runner,
143 &on_produced_and_committed] {
144 task_runner.PostTask(on_produced_and_committed);
145 };
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000146 producer->ProduceEventBatch(posted_on_produced_and_committed);
Lalit Maganti131b6e52018-03-29 18:29:31 +0100147 task_runner.RunUntilCheckpoint(cname, time_for_messages_ms);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000148 }
Lalit Maganti131b6e52018-03-29 18:29:31 +0100149 uint64_t service_ns = service_thread.GetThreadCPUTimeNs() - service_start_ns;
150 uint64_t producer_ns =
151 producer_thread.GetThreadCPUTimeNs() - producer_start_ns;
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000152 uint64_t wall_ns = base::GetWallTimeNs().count() - wall_start_ns;
Lalit Magantidd95ef92018-03-23 09:42:48 +0000153
Lalit Maganti131b6e52018-03-29 18:29:31 +0100154 state.counters["Pro CPU"] = benchmark::Counter(100.0 * producer_ns / wall_ns);
155 state.counters["Ser CPU"] = benchmark::Counter(100.0 * service_ns / wall_ns);
Lalit Magantidd95ef92018-03-23 09:42:48 +0000156 state.counters["Ser ns/m"] =
Lalit Maganti131b6e52018-03-29 18:29:31 +0100157 benchmark::Counter(1.0 * service_ns / message_count);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000158
159 // Read back the buffer just to check correctness.
160 consumer.ReadTraceData();
161 task_runner.RunUntilCheckpoint("readback.complete");
Lalit Maganti131b6e52018-03-29 18:29:31 +0100162 state.SetBytesProcessed(iterations * message_bytes * message_count);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000163
164 consumer.Disconnect();
165}
166
Lalit Maganti131b6e52018-03-29 18:29:31 +0100167void SaturateCpuArgs(benchmark::internal::Benchmark* b) {
168 int min_message_count = 16;
169 int max_message_count = IsBenchmarkFunctionalOnly() ? 1024 : 1024 * 1024;
170 int min_payload = 8;
171 int max_payload = IsBenchmarkFunctionalOnly() ? 256 : 2048;
172 for (int count = min_message_count; count <= max_message_count; count *= 2) {
173 for (int bytes = min_payload; bytes <= max_payload; bytes *= 2) {
174 b->Args({count, bytes, 0 /* speed */});
175 }
176 }
177}
178
179void ConstantRateArgs(benchmark::internal::Benchmark* b) {
180 int message_count = IsBenchmarkFunctionalOnly() ? 2 * 1024 : 128 * 1024;
181 int min_speed = IsBenchmarkFunctionalOnly() ? 64 : 8;
182 int max_speed = IsBenchmarkFunctionalOnly() ? 128 : 128;
183 for (int speed = min_speed; speed <= max_speed; speed *= 2) {
184 b->Args({message_count, 128, speed});
185 b->Args({message_count, 256, speed});
186 }
187}
188}
189
190static void BM_EndToEnd_SaturateCpu(benchmark::State& state) {
191 BenchmarkCommon(state);
192}
193
194BENCHMARK(BM_EndToEnd_SaturateCpu)
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000195 ->Unit(benchmark::kMicrosecond)
196 ->UseRealTime()
Lalit Maganti131b6e52018-03-29 18:29:31 +0100197 ->Apply(SaturateCpuArgs);
198
199static void BM_EndToEnd_ConstantRate(benchmark::State& state) {
200 BenchmarkCommon(state);
Lalit Magantibfc3d3e2018-03-22 20:28:38 +0000201}
Lalit Maganti131b6e52018-03-29 18:29:31 +0100202
203BENCHMARK(BM_EndToEnd_ConstantRate)
204 ->Unit(benchmark::kMicrosecond)
205 ->UseRealTime()
206 ->Apply(ConstantRateArgs);
207} // namespace perfetto