[perftest] Create Timer benchmark
Create a benchmark to test timers with varying degrees of
slack.
ZX-3083
Test: /system/test/sys/perf-test -p --filter Timer
Change-Id: I5e6f2bc0273f15425672005c01cf9c28c2ef0e78
diff --git a/system/utest/perftest/rules.mk b/system/utest/perftest/rules.mk
index 8799e6d..47cea7d 100644
--- a/system/utest/perftest/rules.mk
+++ b/system/utest/perftest/rules.mk
@@ -20,6 +20,7 @@
$(LOCAL_DIR)/runner-test.cpp \
$(LOCAL_DIR)/sleep-test.cpp \
$(LOCAL_DIR)/syscalls-test.cpp \
+ $(LOCAL_DIR)/timer-test.cpp \
MODULE_NAME := perf-test
diff --git a/system/utest/perftest/timer-test.cpp b/system/utest/perftest/timer-test.cpp
new file mode 100644
index 0000000..44b3c99
--- /dev/null
+++ b/system/utest/perftest/timer-test.cpp
@@ -0,0 +1,73 @@
+// Copyright 2018 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 <vector>
+
+#include <fbl/string_printf.h>
+#include <lib/zx/timer.h>
+#include <perftest/perftest.h>
+
+namespace {
+
+struct TimerState {
+ zx::duration wait_time;
+ zx::duration slack_time;
+};
+
+const char* SlackTypeToString(uint32_t slack_type) {
+ switch (slack_type) {
+ case ZX_TIMER_SLACK_LATE:
+ return "SlackLate";
+ case ZX_TIMER_SLACK_EARLY:
+ return "SlackEarly";
+ case ZX_TIMER_SLACK_CENTER:
+ return "SlackCenter";
+ default:
+ ZX_ASSERT_MSG(true, "Slack type unsupported\n");
+ return nullptr;
+ }
+}
+
+// Measures how long a timer takes to fire based on the wait time, slack time,
+// and slack type. This can be useful for measuring the overhead of sleeping.
+// It can also be used to measure the variation in actual sleep times.
+bool TimerWaitTest(perftest::RepeatState* state, TimerState timer_state, uint32_t slack_type) {
+ zx_status_t status;
+ zx::timer timer;
+
+ status = zx::timer::create(slack_type, ZX_CLOCK_MONOTONIC, &timer);
+ ZX_ASSERT(status == ZX_OK);
+
+ while (state->KeepRunning()) {
+ status = timer.set(zx::deadline_after(timer_state.wait_time),
+ timer_state.slack_time);
+ ZX_ASSERT(status == ZX_OK);
+ zx_status_t status = timer.wait_one(
+ ZX_TIMER_SIGNALED, zx::time::infinite(), nullptr);
+ ZX_ASSERT(status == ZX_OK);
+ }
+
+ return true;
+}
+
+void RegisterTests() {
+ const TimerState timers[] = {
+ TimerState{zx::msec(1), zx::usec(0)},
+ TimerState{zx::msec(1), zx::usec(500)}};
+ const uint32_t slack_types[] = {ZX_TIMER_SLACK_LATE,
+ ZX_TIMER_SLACK_EARLY, ZX_TIMER_SLACK_CENTER};
+
+ for (auto timer : timers) {
+ for (auto slack_type : slack_types) {
+ auto name = fbl::StringPrintf("Timer/%lumsWait/%s%luus",
+ timer.wait_time.to_msecs(),
+ SlackTypeToString(slack_type),
+ timer.slack_time.to_usecs());
+ perftest::RegisterTest(name.c_str(), TimerWaitTest, timer, slack_type);
+ }
+ }
+}
+PERFTEST_CTOR(RegisterTests);
+
+} // namespace