1*6dbdd20aSAndroid Build Coastguard Worker /*
2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*6dbdd20aSAndroid Build Coastguard Worker *
4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*6dbdd20aSAndroid Build Coastguard Worker *
8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*6dbdd20aSAndroid Build Coastguard Worker *
10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License.
15*6dbdd20aSAndroid Build Coastguard Worker */
16*6dbdd20aSAndroid Build Coastguard Worker
17*6dbdd20aSAndroid Build Coastguard Worker #include <math.h>
18*6dbdd20aSAndroid Build Coastguard Worker #include <stdint.h>
19*6dbdd20aSAndroid Build Coastguard Worker
20*6dbdd20aSAndroid Build Coastguard Worker #include <algorithm>
21*6dbdd20aSAndroid Build Coastguard Worker #include <atomic>
22*6dbdd20aSAndroid Build Coastguard Worker #include <chrono>
23*6dbdd20aSAndroid Build Coastguard Worker #include <list>
24*6dbdd20aSAndroid Build Coastguard Worker #include <random>
25*6dbdd20aSAndroid Build Coastguard Worker #include <thread>
26*6dbdd20aSAndroid Build Coastguard Worker
27*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/time.h"
28*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/file_utils.h"
29*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/ext/base/string_utils.h"
30*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/tracing.h"
31*6dbdd20aSAndroid Build Coastguard Worker
32*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/config/stress_test_config.gen.h"
33*6dbdd20aSAndroid Build Coastguard Worker #include "protos/perfetto/trace/test_event.pbzero.h"
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard Worker using StressTestConfig = perfetto::protos::gen::StressTestConfig;
36*6dbdd20aSAndroid Build Coastguard Worker
37*6dbdd20aSAndroid Build Coastguard Worker namespace perfetto {
38*6dbdd20aSAndroid Build Coastguard Worker namespace {
39*6dbdd20aSAndroid Build Coastguard Worker
40*6dbdd20aSAndroid Build Coastguard Worker StressTestConfig* g_cfg;
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker class StressTestDataSource : public DataSource<StressTestDataSource> {
43*6dbdd20aSAndroid Build Coastguard Worker public:
44*6dbdd20aSAndroid Build Coastguard Worker constexpr static BufferExhaustedPolicy kBufferExhaustedPolicy =
45*6dbdd20aSAndroid Build Coastguard Worker BufferExhaustedPolicy::kStall;
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard Worker void OnSetup(const SetupArgs& args) override;
48*6dbdd20aSAndroid Build Coastguard Worker void OnStart(const StartArgs&) override;
49*6dbdd20aSAndroid Build Coastguard Worker void OnStop(const StopArgs&) override;
50*6dbdd20aSAndroid Build Coastguard Worker
51*6dbdd20aSAndroid Build Coastguard Worker private:
52*6dbdd20aSAndroid Build Coastguard Worker class Worker {
53*6dbdd20aSAndroid Build Coastguard Worker public:
Worker(uint32_t id)54*6dbdd20aSAndroid Build Coastguard Worker explicit Worker(uint32_t id) : id_(id) {}
55*6dbdd20aSAndroid Build Coastguard Worker void Start();
56*6dbdd20aSAndroid Build Coastguard Worker void Stop();
~Worker()57*6dbdd20aSAndroid Build Coastguard Worker ~Worker() { Stop(); }
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard Worker private:
60*6dbdd20aSAndroid Build Coastguard Worker void WorkerMain(uint32_t worker_id);
61*6dbdd20aSAndroid Build Coastguard Worker void FillPayload(const StressTestConfig::WriterTiming&,
62*6dbdd20aSAndroid Build Coastguard Worker uint32_t seq,
63*6dbdd20aSAndroid Build Coastguard Worker uint32_t nesting,
64*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::TestEvent::TestPayload*);
65*6dbdd20aSAndroid Build Coastguard Worker
66*6dbdd20aSAndroid Build Coastguard Worker const uint32_t id_;
67*6dbdd20aSAndroid Build Coastguard Worker std::thread thread_;
68*6dbdd20aSAndroid Build Coastguard Worker std::atomic<bool> quit_;
69*6dbdd20aSAndroid Build Coastguard Worker std::minstd_rand0 rnd_seq_;
70*6dbdd20aSAndroid Build Coastguard Worker
71*6dbdd20aSAndroid Build Coastguard Worker // Use a different engine for the generation of random value, keep rnd_seq_
72*6dbdd20aSAndroid Build Coastguard Worker // dedicated to generating deterministic sequences.
73*6dbdd20aSAndroid Build Coastguard Worker std::minstd_rand0 rnd_gen_;
74*6dbdd20aSAndroid Build Coastguard Worker };
75*6dbdd20aSAndroid Build Coastguard Worker
76*6dbdd20aSAndroid Build Coastguard Worker std::list<Worker> workers_;
77*6dbdd20aSAndroid Build Coastguard Worker };
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard Worker // Called before the tracing session starts.
OnSetup(const SetupArgs &)80*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::OnSetup(const SetupArgs&) {
81*6dbdd20aSAndroid Build Coastguard Worker for (uint32_t i = 0; i < std::max(g_cfg->num_threads(), 1u); ++i)
82*6dbdd20aSAndroid Build Coastguard Worker workers_.emplace_back(i);
83*6dbdd20aSAndroid Build Coastguard Worker }
84*6dbdd20aSAndroid Build Coastguard Worker
85*6dbdd20aSAndroid Build Coastguard Worker // Called when the tracing session starts.
OnStart(const StartArgs &)86*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::OnStart(const StartArgs&) {
87*6dbdd20aSAndroid Build Coastguard Worker for (auto& worker : workers_)
88*6dbdd20aSAndroid Build Coastguard Worker worker.Start();
89*6dbdd20aSAndroid Build Coastguard Worker }
90*6dbdd20aSAndroid Build Coastguard Worker
91*6dbdd20aSAndroid Build Coastguard Worker // Called when the tracing session ends.
OnStop(const StopArgs &)92*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::OnStop(const StopArgs&) {
93*6dbdd20aSAndroid Build Coastguard Worker for (auto& worker : workers_)
94*6dbdd20aSAndroid Build Coastguard Worker worker.Stop();
95*6dbdd20aSAndroid Build Coastguard Worker workers_.clear();
96*6dbdd20aSAndroid Build Coastguard Worker }
97*6dbdd20aSAndroid Build Coastguard Worker
Start()98*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::Worker::Start() {
99*6dbdd20aSAndroid Build Coastguard Worker quit_.store(false);
100*6dbdd20aSAndroid Build Coastguard Worker thread_ = std::thread(&StressTestDataSource::Worker::WorkerMain, this, id_);
101*6dbdd20aSAndroid Build Coastguard Worker }
102*6dbdd20aSAndroid Build Coastguard Worker
Stop()103*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::Worker::Stop() {
104*6dbdd20aSAndroid Build Coastguard Worker if (!thread_.joinable() || quit_)
105*6dbdd20aSAndroid Build Coastguard Worker return;
106*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Stopping worker %u", id_);
107*6dbdd20aSAndroid Build Coastguard Worker quit_.store(true);
108*6dbdd20aSAndroid Build Coastguard Worker thread_.join();
109*6dbdd20aSAndroid Build Coastguard Worker }
110*6dbdd20aSAndroid Build Coastguard Worker
WorkerMain(uint32_t worker_id)111*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::Worker::WorkerMain(uint32_t worker_id) {
112*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Worker %u starting", worker_id);
113*6dbdd20aSAndroid Build Coastguard Worker rnd_seq_ = std::minstd_rand0(0);
114*6dbdd20aSAndroid Build Coastguard Worker int64_t t_start = base::GetBootTimeNs().count();
115*6dbdd20aSAndroid Build Coastguard Worker int64_t num_msgs = 0;
116*6dbdd20aSAndroid Build Coastguard Worker
117*6dbdd20aSAndroid Build Coastguard Worker const int64_t max_msgs = g_cfg->max_events()
118*6dbdd20aSAndroid Build Coastguard Worker ? static_cast<int64_t>(g_cfg->max_events())
119*6dbdd20aSAndroid Build Coastguard Worker : INT64_MAX;
120*6dbdd20aSAndroid Build Coastguard Worker bool is_last = false;
121*6dbdd20aSAndroid Build Coastguard Worker while (!is_last) {
122*6dbdd20aSAndroid Build Coastguard Worker is_last = quit_ || ++num_msgs >= max_msgs;
123*6dbdd20aSAndroid Build Coastguard Worker
124*6dbdd20aSAndroid Build Coastguard Worker const int64_t now = base::GetBootTimeNs().count();
125*6dbdd20aSAndroid Build Coastguard Worker const auto elapsed_ms = static_cast<uint64_t>((now - t_start) / 1000000);
126*6dbdd20aSAndroid Build Coastguard Worker
127*6dbdd20aSAndroid Build Coastguard Worker const auto* timings = &g_cfg->steady_state_timings();
128*6dbdd20aSAndroid Build Coastguard Worker if (g_cfg->burst_period_ms() &&
129*6dbdd20aSAndroid Build Coastguard Worker elapsed_ms % g_cfg->burst_period_ms() >
130*6dbdd20aSAndroid Build Coastguard Worker (g_cfg->burst_period_ms() - g_cfg->burst_duration_ms())) {
131*6dbdd20aSAndroid Build Coastguard Worker timings = &g_cfg->burst_timings();
132*6dbdd20aSAndroid Build Coastguard Worker }
133*6dbdd20aSAndroid Build Coastguard Worker std::normal_distribution<> rate_dist{timings->rate_mean(),
134*6dbdd20aSAndroid Build Coastguard Worker timings->rate_stddev()};
135*6dbdd20aSAndroid Build Coastguard Worker
136*6dbdd20aSAndroid Build Coastguard Worker double period_ns = 1e9 / rate_dist(rnd_gen_);
137*6dbdd20aSAndroid Build Coastguard Worker period_ns = isnan(period_ns) || period_ns == 0.0 ? 1 : period_ns;
138*6dbdd20aSAndroid Build Coastguard Worker double expected_msgs = static_cast<double>(now - t_start) / period_ns;
139*6dbdd20aSAndroid Build Coastguard Worker int64_t delay_ns = 0;
140*6dbdd20aSAndroid Build Coastguard Worker if (static_cast<int64_t>(expected_msgs) < num_msgs)
141*6dbdd20aSAndroid Build Coastguard Worker delay_ns = static_cast<int64_t>(period_ns);
142*6dbdd20aSAndroid Build Coastguard Worker std::this_thread::sleep_for(
143*6dbdd20aSAndroid Build Coastguard Worker std::chrono::nanoseconds(static_cast<int64_t>(delay_ns)));
144*6dbdd20aSAndroid Build Coastguard Worker
145*6dbdd20aSAndroid Build Coastguard Worker StressTestDataSource::Trace([&](StressTestDataSource::TraceContext ctx) {
146*6dbdd20aSAndroid Build Coastguard Worker const uint32_t seq = static_cast<uint32_t>(rnd_seq_());
147*6dbdd20aSAndroid Build Coastguard Worker auto packet = ctx.NewTracePacket();
148*6dbdd20aSAndroid Build Coastguard Worker packet->set_timestamp(static_cast<uint64_t>(now));
149*6dbdd20aSAndroid Build Coastguard Worker auto* test_event = packet->set_for_testing();
150*6dbdd20aSAndroid Build Coastguard Worker test_event->set_seq_value(seq);
151*6dbdd20aSAndroid Build Coastguard Worker test_event->set_counter(static_cast<uint64_t>(num_msgs));
152*6dbdd20aSAndroid Build Coastguard Worker if (is_last)
153*6dbdd20aSAndroid Build Coastguard Worker test_event->set_is_last(true);
154*6dbdd20aSAndroid Build Coastguard Worker
155*6dbdd20aSAndroid Build Coastguard Worker FillPayload(*timings, seq, g_cfg->nesting(), test_event->set_payload());
156*6dbdd20aSAndroid Build Coastguard Worker }); // Trace().
157*6dbdd20aSAndroid Build Coastguard Worker
158*6dbdd20aSAndroid Build Coastguard Worker } // while (!quit)
159*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DLOG("Worker done");
160*6dbdd20aSAndroid Build Coastguard Worker }
161*6dbdd20aSAndroid Build Coastguard Worker
FillPayload(const StressTestConfig::WriterTiming & timings,uint32_t seq,uint32_t nesting,protos::pbzero::TestEvent::TestPayload * payload)162*6dbdd20aSAndroid Build Coastguard Worker void StressTestDataSource::Worker::FillPayload(
163*6dbdd20aSAndroid Build Coastguard Worker const StressTestConfig::WriterTiming& timings,
164*6dbdd20aSAndroid Build Coastguard Worker uint32_t seq,
165*6dbdd20aSAndroid Build Coastguard Worker uint32_t nesting,
166*6dbdd20aSAndroid Build Coastguard Worker protos::pbzero::TestEvent::TestPayload* payload) {
167*6dbdd20aSAndroid Build Coastguard Worker // Write the payload in two halves, optionally with some delay in the
168*6dbdd20aSAndroid Build Coastguard Worker // middle.
169*6dbdd20aSAndroid Build Coastguard Worker std::normal_distribution<> msg_size_dist{timings.payload_mean(),
170*6dbdd20aSAndroid Build Coastguard Worker timings.payload_stddev()};
171*6dbdd20aSAndroid Build Coastguard Worker auto payload_size =
172*6dbdd20aSAndroid Build Coastguard Worker static_cast<uint32_t>(std::max(std::round(msg_size_dist(rnd_gen_)), 0.0));
173*6dbdd20aSAndroid Build Coastguard Worker std::string buf;
174*6dbdd20aSAndroid Build Coastguard Worker buf.resize(payload_size / 2);
175*6dbdd20aSAndroid Build Coastguard Worker for (size_t i = 0; i < buf.size(); ++i) {
176*6dbdd20aSAndroid Build Coastguard Worker buf[i] = static_cast<char>(33 + ((seq + i) % 64)); // Stay ASCII.
177*6dbdd20aSAndroid Build Coastguard Worker }
178*6dbdd20aSAndroid Build Coastguard Worker payload->add_str(buf);
179*6dbdd20aSAndroid Build Coastguard Worker payload->set_remaining_nesting_depth(nesting);
180*6dbdd20aSAndroid Build Coastguard Worker if (timings.payload_write_time_ms() > 0) {
181*6dbdd20aSAndroid Build Coastguard Worker std::this_thread::sleep_for(
182*6dbdd20aSAndroid Build Coastguard Worker std::chrono::milliseconds(timings.payload_write_time_ms()));
183*6dbdd20aSAndroid Build Coastguard Worker }
184*6dbdd20aSAndroid Build Coastguard Worker
185*6dbdd20aSAndroid Build Coastguard Worker if (nesting > 0)
186*6dbdd20aSAndroid Build Coastguard Worker FillPayload(timings, seq, nesting - 1, payload->add_nested());
187*6dbdd20aSAndroid Build Coastguard Worker
188*6dbdd20aSAndroid Build Coastguard Worker payload->add_str(buf);
189*6dbdd20aSAndroid Build Coastguard Worker }
190*6dbdd20aSAndroid Build Coastguard Worker } // namespace
191*6dbdd20aSAndroid Build Coastguard Worker
192*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(StressTestDataSource);
193*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(StressTestDataSource);
194*6dbdd20aSAndroid Build Coastguard Worker
195*6dbdd20aSAndroid Build Coastguard Worker } // namespace perfetto
196*6dbdd20aSAndroid Build Coastguard Worker
main()197*6dbdd20aSAndroid Build Coastguard Worker int main() {
198*6dbdd20aSAndroid Build Coastguard Worker perfetto::TracingInitArgs args;
199*6dbdd20aSAndroid Build Coastguard Worker args.backends = perfetto::kSystemBackend;
200*6dbdd20aSAndroid Build Coastguard Worker
201*6dbdd20aSAndroid Build Coastguard Worker std::string config_blob;
202*6dbdd20aSAndroid Build Coastguard Worker if (isatty(fileno(stdin)))
203*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_LOG("Reading StressTestConfig proto from stdin");
204*6dbdd20aSAndroid Build Coastguard Worker perfetto::base::ReadFileStream(stdin, &config_blob);
205*6dbdd20aSAndroid Build Coastguard Worker
206*6dbdd20aSAndroid Build Coastguard Worker StressTestConfig cfg;
207*6dbdd20aSAndroid Build Coastguard Worker perfetto::g_cfg = &cfg;
208*6dbdd20aSAndroid Build Coastguard Worker if (config_blob.empty() || !cfg.ParseFromString(config_blob))
209*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_FATAL("A StressTestConfig blob must be passed into stdin");
210*6dbdd20aSAndroid Build Coastguard Worker
211*6dbdd20aSAndroid Build Coastguard Worker if (cfg.shmem_page_size_kb())
212*6dbdd20aSAndroid Build Coastguard Worker args.shmem_page_size_hint_kb = cfg.shmem_page_size_kb();
213*6dbdd20aSAndroid Build Coastguard Worker if (cfg.shmem_size_kb())
214*6dbdd20aSAndroid Build Coastguard Worker args.shmem_page_size_hint_kb = cfg.shmem_size_kb();
215*6dbdd20aSAndroid Build Coastguard Worker
216*6dbdd20aSAndroid Build Coastguard Worker perfetto::Tracing::Initialize(args);
217*6dbdd20aSAndroid Build Coastguard Worker perfetto::DataSourceDescriptor dsd;
218*6dbdd20aSAndroid Build Coastguard Worker dsd.set_name("perfetto.stress_test");
219*6dbdd20aSAndroid Build Coastguard Worker perfetto::StressTestDataSource::Register(dsd);
220*6dbdd20aSAndroid Build Coastguard Worker
221*6dbdd20aSAndroid Build Coastguard Worker for (;;) {
222*6dbdd20aSAndroid Build Coastguard Worker std::this_thread::sleep_for(std::chrono::seconds(30));
223*6dbdd20aSAndroid Build Coastguard Worker }
224*6dbdd20aSAndroid Build Coastguard Worker }
225