blob: 01bfdb0119999971478d497b5fcda1b7715c0be7 [file] [log] [blame]
// Copyright 2020 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 <fuchsia/kernel/cpp/fidl.h>
#include <lib/inspect/cpp/reader.h>
#include <lib/sys/cpp/service_directory.h>
#include <zircon/status.h>
#include <iterator>
#include <utility>
#include <perftest/results.h>
namespace {
constexpr std::pair<const char*, const char*> kSteps[] = {
{"boot.timeline.zbi", "KernelBootLoader"},
{"boot.timeline.virtual", "KernelBootPhysical"},
{"boot.timeline.threading", "KernelBootThreads"},
{"boot.timeline.userboot", "KernelBootUser"},
{"boot.timeline.init", "KernelBootComplete"},
};
perftest::ResultsSet BootTimeline() {
fuchsia::kernel::CounterSyncPtr kcounter;
auto environment_services = ::sys::ServiceDirectory::CreateFromNamespace();
environment_services->Connect(kcounter.NewRequest());
fuchsia::mem::Buffer buffer;
zx_status_t status;
zx_status_t get_status = kcounter->GetInspectVmo(&status, &buffer);
ZX_ASSERT_MSG(get_status == ZX_OK, "GetInspectVmo: %s", zx_status_get_string(get_status));
ZX_ASSERT_MSG(status == ZX_OK, "GetInspectVmo yields status %s",
zx_status_get_string(get_status));
auto result = inspect::ReadFromVmo(buffer.vmo);
ZX_ASSERT_MSG(result.is_ok(), "ReadFromVmo failed");
auto root = result.take_value();
auto timeline = root.GetByPath({"boot", "timeline"});
ZX_ASSERT_MSG(timeline, "boot.timeline not found");
const auto& properties = timeline->node().properties();
ZX_ASSERT(properties.size() == std::size(kSteps));
double ms_per_tick = 1000.0 / static_cast<double>(zx_ticks_per_second());
perftest::ResultsSet results;
int64_t last_step_ticks = 0;
for (auto [name, result_name] : kSteps) {
auto it = std::find_if(properties.begin(), properties.end(),
[name = name](const auto& m) { return m.name() == name; });
ZX_ASSERT_MSG(it != properties.end(), "%s not found", name);
ZX_ASSERT_MSG(
it->Contains<inspect::IntPropertyValue>(),
"All properties in kSteps are expected to be IntMetric: name: %s actual format: %d", name,
static_cast<int>(it->format()));
int64_t step_ticks = it->Get<inspect::IntPropertyValue>().value();
int64_t elapsed = step_ticks - last_step_ticks;
double elapsed_ms = static_cast<double>(elapsed) * ms_per_tick;
last_step_ticks = step_ticks;
auto* t = results.AddTestCase("fuchsia.kernel.boot", result_name, "milliseconds");
t->AppendValue(elapsed_ms);
}
ZX_ASSERT(results.results()->size() == std::size(kSteps));
return results;
}
} // namespace
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s OUTFILE.json\n", argv[0]);
return 1;
}
const char* outfile = argv[1];
perftest::ResultsSet results = BootTimeline();
return results.WriteJSONFile(outfile) ? 0 : 1;
}