blob: 6a3c59e34e3d162155d6e86123aac9c9d17ff87e [file] [log] [blame]
// Copyright 2025 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 <lib/syslog/cpp/macros.h>
#include <string.h>
#include <sys/mount.h>
#include <cerrno>
#include <cstdio>
#include <memory>
#include <perftest/perftest.h>
// Test fixture to manage mounting and unmounting tracefs.
class TraceFs {
public:
TraceFs() = default;
TraceFs(TraceFs&&) = default;
TraceFs& operator=(TraceFs&&) = default;
TraceFs(const TraceFs&) = delete;
TraceFs& operator=(const TraceFs&) = delete;
~TraceFs() { umount("/sys/kernel/tracing"); }
// RAII wrapper for FILE*.
using unique_file = std::unique_ptr<FILE, decltype(&fclose)>;
static std::optional<TraceFs> Mount() {
if (mount("tracefs", "/sys/kernel/tracing", "tracefs", MS_NODEV, nullptr) != 0) {
fprintf(stderr, "Failed to mount tracefs!: %s\n", strerror(errno));
return std::nullopt;
}
return std::make_optional<TraceFs>();
}
unique_file Open(const char* path, const char* mode) const {
FILE* file = fopen(path, mode);
if (file == nullptr) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
}
return {file, &fclose};
}
};
namespace {
// Measure the time taken to write an atrace style event to tracefs
bool WriteEvent(perftest::RepeatState* state) {
std::optional<TraceFs> tracefs = TraceFs::Mount();
FX_CHECK(tracefs.has_value());
auto tracing_file = tracefs->Open("/sys/kernel/tracing/tracing_on", "w");
FX_CHECK(tracing_file != nullptr);
fputs("1\n", tracing_file.get());
// Don't forget to flush! Or else we may not actually write the file.
fflush(tracing_file.get());
auto marker_file = tracefs->Open("/sys/kernel/tracing/trace_marker", "w");
FX_CHECK(marker_file != nullptr);
while (state->KeepRunning()) {
fputs("B|1234|slice", marker_file.get());
// We flush every time so we actually measure the trip into the syscall.
fflush(marker_file.get());
}
fputs("0\n", tracing_file.get());
return true;
}
// Measure the time to write to tracefs when tracefs isn't enabled. This measures the syscall and
// vfs overhead in tracefs.
bool WriteDisabled(perftest::RepeatState* state) {
std::optional<TraceFs> tracefs = TraceFs::Mount();
FX_CHECK(tracefs.has_value());
auto marker_file = tracefs->Open("/sys/kernel/tracing/trace_marker", "w");
FX_CHECK(marker_file != nullptr);
while (state->KeepRunning()) {
fputs("B|1234|slice", marker_file.get());
// We flush every time so we actually measure the trip into the syscall.
fflush(marker_file.get());
}
return true;
}
void RegisterTests() {
perftest::RegisterTest("TraceFs/WriteDisabled", WriteDisabled);
perftest::RegisterTest("TraceFs/WriteEvent", WriteEvent);
}
PERFTEST_CTOR(RegisterTests)
} // namespace