blob: 97ade917a01833b0645093aa81fbff83a7777ed4 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "benchmarks.h"
#include <inttypes.h>
#include <stdio.h>
#include <fbl/function.h>
#include <lib/async/cpp/task.h>
#include <trace-engine/buffer_internal.h>
#include <trace-engine/instrumentation.h>
#include <trace/event.h>
#include "handler.h"
#include "runner.h"
namespace {
using Benchmark = fbl::Function<void()>;
class Runner {
public:
Runner(bool enabled, const BenchmarkSpec* spec)
: enabled_(enabled), spec_(spec) {}
void Run(const char* name, Benchmark benchmark) {
if (enabled_) {
// The trace engine needs to run in its own thread in order to
// process buffer full requests in streaming mode while the
// benchmark is running. Note that records will still get lost
// if the engine thread is not scheduled frequently enough. This
// is a stress test so all the app is doing is filling the trace
// buffer. :-)
async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
BenchmarkHandler handler(&loop, spec_->name, spec_->mode,
spec_->buffer_size);
loop.StartThread("trace-engine loop", nullptr);
handler.Start();
RunAndMeasure(name, spec_->num_iterations, benchmark);
// Acquire the context before we stop. We can't after we stop
// as the context has likely been released (no more
// references).
trace::internal::trace_buffer_header header;
{
auto context = trace::TraceProlongedContext::Acquire();
trace_stop_engine(ZX_OK);
trace_context_snapshot_buffer_header(context.get(), &header);
}
if (handler.mode() == TRACE_BUFFERING_MODE_ONESHOT) {
ZX_DEBUG_ASSERT(header.wrapped_count == 0);
} else {
printf("Trace buffer wrapped %u times, %" PRIu64 " records dropped\n",
header.wrapped_count, header.num_records_dropped);
}
loop.JoinThreads();
} else {
// For the disabled benchmarks we just use the default number
// of iterations.
ZX_DEBUG_ASSERT(spec_ == nullptr);
RunAndMeasure(name, benchmark);
}
}
private:
const bool enabled_;
// nullptr if |!enabled_|.
const BenchmarkSpec* spec_;
};
void RunBenchmarks(bool tracing_enabled, const BenchmarkSpec* spec) {
Runner runner(tracing_enabled, spec);
runner.Run("is enabled", [] {
trace_is_enabled();
});
runner.Run("is category enabled", [] {
trace_is_category_enabled("+enabled");
});
if (tracing_enabled) {
runner.Run("is category enabled for disabled category", [] {
trace_is_category_enabled("-disabled");
});
}
runner.Run("acquire / release context", [] {
trace_context_t* context = trace_acquire_context();
if (unlikely(context))
trace_release_context(context);
});
runner.Run("acquire / release context for category", [] {
trace_string_ref_t category_ref;
trace_context_t* context = trace_acquire_context_for_category(
"+enabled", &category_ref);
if (unlikely(context))
trace_release_context(context);
});
if (tracing_enabled) {
runner.Run("acquire / release context for disabled category", [] {
trace_string_ref_t category_ref;
trace_context_t* context = trace_acquire_context_for_category(
"-disabled", &category_ref);
ZX_DEBUG_ASSERT(!context);
});
}
runner.Run("TRACE_DURATION_BEGIN macro with 0 arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name");
});
runner.Run("TRACE_DURATION_BEGIN macro with 1 int32 argument", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1);
});
runner.Run("TRACE_DURATION_BEGIN macro with 1 double argument", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1.);
});
runner.Run("TRACE_DURATION_BEGIN macro with 1 string argument", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", "string1");
});
runner.Run("TRACE_DURATION_BEGIN macro with 4 int32 arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1, "k2", 2, "k3", 3, "k4", 4);
});
runner.Run("TRACE_DURATION_BEGIN macro with 4 double arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1., "k2", 2., "k3", 3., "k4", 4.);
});
runner.Run("TRACE_DURATION_BEGIN macro with 4 string arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", "string1", "k2", "string2", "k3", "string3", "k4", "string4");
});
runner.Run("TRACE_DURATION_BEGIN macro with 8 int32 arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1, "k2", 2, "k3", 3, "k4", 4,
"k5", 5, "k6", 6, "k7", 7, "k8", 8);
});
runner.Run("TRACE_DURATION_BEGIN macro with 8 double arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", 1., "k2", 2., "k3", 3., "k4", 4.,
"k5", 4., "k6", 5., "k7", 7., "k8", 8.);
});
runner.Run("TRACE_DURATION_BEGIN macro with 8 string arguments", [] {
TRACE_DURATION_BEGIN("+enabled", "name",
"k1", "string1", "k2", "string2", "k3", "string3", "k4", "string4",
"k5", "string5", "k6", "string6", "k7", "string7", "k8", "string8");
});
if (tracing_enabled) {
runner.Run("TRACE_DURATION_BEGIN macro with 0 arguments for disabled category", [] {
TRACE_DURATION_BEGIN("-disabled", "name");
});
runner.Run("TRACE_DURATION_BEGIN macro with 1 int32 argument for disabled category", [] {
TRACE_DURATION_BEGIN("-disabled", "name",
"k1", 1);
});
runner.Run("TRACE_DURATION_BEGIN macro with 4 int32 arguments for disabled category", [] {
TRACE_DURATION_BEGIN("-disabled", "name",
"k1", 1, "k2", 2, "k3", 3, "k4", 4);
});
runner.Run("TRACE_DURATION_BEGIN macro with 8 int32 arguments for disabled category", [] {
TRACE_DURATION_BEGIN("-disabled", "name",
"k1", 1, "k2", 2, "k3", 3, "k4", 4,
"k5", 5, "k6", 6, "k7", 7, "k8", 8);
});
}
}
} // namespace
void RunTracingDisabledBenchmarks() {
puts("\nRunning benchmarks with tracing disabled...\n");
RunBenchmarks(false, nullptr);
}
void RunTracingEnabledBenchmarks(const BenchmarkSpec* spec) {
// No trailing \n on purpose. The extra blank line is provided by
// BenchmarkHandler.Start().
puts("\nRunning benchmarks with tracing enabled...");
RunBenchmarks(true, spec);
}