1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "benchmarks.h"
6
7 #include <inttypes.h>
8 #include <stdio.h>
9
10 #include <fbl/function.h>
11 #include <lib/async/cpp/task.h>
12 #include <trace-engine/buffer_internal.h>
13 #include <trace-engine/instrumentation.h>
14 #include <trace/event.h>
15 #include <trace-vthread/event_vthread.h>
16
17 #include "handler.h"
18 #include "runner.h"
19
20 namespace {
21
22 using Benchmark = fbl::Function<void()>;
23
24 class Runner {
25 public:
Runner(bool enabled,const BenchmarkSpec * spec)26 Runner(bool enabled, const BenchmarkSpec* spec)
27 : enabled_(enabled), spec_(spec) {}
28
Run(const char * name,Benchmark benchmark)29 void Run(const char* name, Benchmark benchmark) {
30 if (enabled_) {
31 // The trace engine needs to run in its own thread in order to
32 // process buffer full requests in streaming mode while the
33 // benchmark is running. Note that records will still get lost
34 // if the engine thread is not scheduled frequently enough. This
35 // is a stress test so all the app is doing is filling the trace
36 // buffer. :-)
37 async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
38 BenchmarkHandler handler(&loop, spec_->mode, spec_->buffer_size);
39
40 loop.StartThread("trace-engine loop", nullptr);
41
42 RunAndMeasure(name, spec_->name, spec_->num_iterations, benchmark,
43 [&handler] () { handler.Start(); },
44 [&handler] () { handler.Stop(); });
45
46 loop.Quit();
47 loop.JoinThreads();
48 } else {
49 // For the disabled benchmarks we just use the default number
50 // of iterations.
51 RunAndMeasure(name, spec_->name, benchmark, [](){}, [](){});
52 }
53 }
54
55 private:
56 const bool enabled_;
57 // nullptr if |!enabled_|.
58 const BenchmarkSpec* spec_;
59 };
60
RunBenchmarks(bool tracing_enabled,const BenchmarkSpec * spec)61 void RunBenchmarks(bool tracing_enabled, const BenchmarkSpec* spec) {
62 Runner runner(tracing_enabled, spec);
63
64 runner.Run("is enabled", [] {
65 trace_is_enabled();
66 });
67
68 runner.Run("is category enabled", [] {
69 trace_is_category_enabled("+enabled");
70 });
71
72 if (tracing_enabled) {
73 runner.Run("is category enabled for disabled category", [] {
74 trace_is_category_enabled("-disabled");
75 });
76 }
77
78 runner.Run("acquire / release context", [] {
79 trace_context_t* context = trace_acquire_context();
80 if (unlikely(context))
81 trace_release_context(context);
82 });
83
84 runner.Run("acquire / release context for category", [] {
85 trace_string_ref_t category_ref;
86 trace_context_t* context = trace_acquire_context_for_category(
87 "+enabled", &category_ref);
88 if (unlikely(context))
89 trace_release_context(context);
90 });
91
92 if (tracing_enabled) {
93 runner.Run("acquire / release context for disabled category", [] {
94 trace_string_ref_t category_ref;
95 trace_context_t* context = trace_acquire_context_for_category(
96 "-disabled", &category_ref);
97 ZX_DEBUG_ASSERT(!context);
98 });
99 }
100
101 runner.Run("TRACE_DURATION_BEGIN macro with 0 arguments", [] {
102 TRACE_DURATION_BEGIN("+enabled", "name");
103 });
104
105 runner.Run("TRACE_DURATION_BEGIN macro with 1 int32 argument", [] {
106 TRACE_DURATION_BEGIN("+enabled", "name",
107 "k1", 1);
108 });
109
110 runner.Run("TRACE_DURATION_BEGIN macro with 1 double argument", [] {
111 TRACE_DURATION_BEGIN("+enabled", "name",
112 "k1", 1.);
113 });
114
115 runner.Run("TRACE_DURATION_BEGIN macro with 1 string argument", [] {
116 TRACE_DURATION_BEGIN("+enabled", "name",
117 "k1", "string1");
118 });
119
120 runner.Run("TRACE_DURATION_BEGIN macro with 4 int32 arguments", [] {
121 TRACE_DURATION_BEGIN("+enabled", "name",
122 "k1", 1, "k2", 2, "k3", 3, "k4", 4);
123 });
124
125 runner.Run("TRACE_DURATION_BEGIN macro with 4 double arguments", [] {
126 TRACE_DURATION_BEGIN("+enabled", "name",
127 "k1", 1., "k2", 2., "k3", 3., "k4", 4.);
128 });
129
130 runner.Run("TRACE_DURATION_BEGIN macro with 4 string arguments", [] {
131 TRACE_DURATION_BEGIN("+enabled", "name",
132 "k1", "string1", "k2", "string2", "k3", "string3", "k4", "string4");
133 });
134
135 runner.Run("TRACE_DURATION_BEGIN macro with 8 int32 arguments", [] {
136 TRACE_DURATION_BEGIN("+enabled", "name",
137 "k1", 1, "k2", 2, "k3", 3, "k4", 4,
138 "k5", 5, "k6", 6, "k7", 7, "k8", 8);
139 });
140
141 runner.Run("TRACE_DURATION_BEGIN macro with 8 double arguments", [] {
142 TRACE_DURATION_BEGIN("+enabled", "name",
143 "k1", 1., "k2", 2., "k3", 3., "k4", 4.,
144 "k5", 4., "k6", 5., "k7", 7., "k8", 8.);
145 });
146
147 runner.Run("TRACE_DURATION_BEGIN macro with 8 string arguments", [] {
148 TRACE_DURATION_BEGIN("+enabled", "name",
149 "k1", "string1", "k2", "string2", "k3", "string3", "k4", "string4",
150 "k5", "string5", "k6", "string6", "k7", "string7", "k8", "string8");
151 });
152
153 runner.Run("TRACE_VTHREAD_DURATION_BEGIN macro with 0 arguments", [] {
154 TRACE_VTHREAD_DURATION_BEGIN("+enabled", "name", "vthread", 1, zx_ticks_get());
155 });
156
157
158 if (tracing_enabled) {
159 runner.Run("TRACE_DURATION_BEGIN macro with 0 arguments for disabled category", [] {
160 TRACE_DURATION_BEGIN("-disabled", "name");
161 });
162
163 runner.Run("TRACE_DURATION_BEGIN macro with 1 int32 argument for disabled category", [] {
164 TRACE_DURATION_BEGIN("-disabled", "name",
165 "k1", 1);
166 });
167
168 runner.Run("TRACE_DURATION_BEGIN macro with 4 int32 arguments for disabled category", [] {
169 TRACE_DURATION_BEGIN("-disabled", "name",
170 "k1", 1, "k2", 2, "k3", 3, "k4", 4);
171 });
172
173 runner.Run("TRACE_DURATION_BEGIN macro with 8 int32 arguments for disabled category", [] {
174 TRACE_DURATION_BEGIN("-disabled", "name",
175 "k1", 1, "k2", 2, "k3", 3, "k4", 4,
176 "k5", 5, "k6", 6, "k7", 7, "k8", 8);
177 });
178
179 runner.Run("TRACE_VTHREAD_DURATION_BEGIN macro with 0 arguments for disabled category", [] {
180 TRACE_VTHREAD_DURATION_BEGIN("-disabled", "name", "vthread", 1, zx_ticks_get());
181 });
182 }
183 }
184
185 } // namespace
186
RunTracingDisabledBenchmarks()187 void RunTracingDisabledBenchmarks() {
188 static const BenchmarkSpec spec = {
189 "disabled",
190 TRACE_BUFFERING_MODE_ONESHOT, // unused
191 0,
192 kDefaultRunIterations,
193 };
194 RunBenchmarks(false, &spec);
195 }
196
RunTracingEnabledBenchmarks(const BenchmarkSpec * spec)197 void RunTracingEnabledBenchmarks(const BenchmarkSpec* spec) {
198 // No trailing \n on purpose. The extra blank line is provided by
199 // BenchmarkHandler.Start().
200 RunBenchmarks(true, spec);
201 }
202