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