[hlcpp][benchmarks] HLCPP benchmarks for "echo calls"
This adds benchmarking of making a FIDL call - in particular a call that
echos the value back to the client. This is intended to detect
regressions that make HLCPP calls slower. The sync API is used here on
the client side but a similar benchmark could be made with the async
API.
HLCPP/EchoCall/ByteVector/256/Steps.EchoCall/WallTime added - - 7934 +/- 199 ns
HLCPP/EchoCall/ByteVector/4096/Steps.EchoCall/WallTime added - - 12037 +/- 196 ns
Change-Id: I5c1a4a2ab9a1e7e089b7743cd5e4808470699f04
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/405315
Reviewed-by: Yifei Teng <yifeit@google.com>
Testability-Review: Yifei Teng <yifeit@google.com>
Commit-Queue: Benjamin Prosnitz <bprosnitz@google.com>
diff --git a/src/tests/benchmarks/fidl/hlcpp/echo_call_benchmark_util.h b/src/tests/benchmarks/fidl/hlcpp/echo_call_benchmark_util.h
new file mode 100644
index 0000000..d370862
--- /dev/null
+++ b/src/tests/benchmarks/fidl/hlcpp/echo_call_benchmark_util.h
@@ -0,0 +1,57 @@
+// 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.
+
+#ifndef SRC_TESTS_BENCHMARKS_FIDL_HLCPP_ECHO_CALL_BENCHMARK_UTIL_H_
+#define SRC_TESTS_BENCHMARKS_FIDL_HLCPP_ECHO_CALL_BENCHMARK_UTIL_H_
+
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/async-loop/default.h>
+#include <lib/fidl/cpp/binding.h>
+
+#include <perftest/perftest.h>
+
+namespace hlcpp_benchmarks {
+
+template <typename ProtocolType, typename FidlType>
+class EchoServerImpl : public ProtocolType {
+ void Echo(FidlType val, typename ProtocolType::EchoCallback callback) override { callback(val); }
+};
+
+template <typename ProtocolType, typename BuilderFunc>
+bool EchoCallBenchmark(perftest::RepeatState* state, BuilderFunc builder) {
+ using FidlType = std::invoke_result_t<BuilderFunc>;
+
+ state->DeclareStep("Setup/WallTime");
+ state->DeclareStep("EchoCall/WallTime");
+ state->DeclareStep("Teardown/WallTime");
+
+ async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
+ fidl::SynchronousInterfacePtr<ProtocolType> ptr;
+
+ EchoServerImpl<ProtocolType, FidlType> server;
+ fidl::Binding<ProtocolType> server_binding(&server);
+ server_binding.Bind(ptr.NewRequest());
+
+ loop.StartThread();
+
+ while (state->KeepRunning()) {
+ FidlType in = builder();
+
+ state->NextStep(); // End: Setup. Begin: EchoCall.
+
+ FidlType out;
+ zx_status_t status = ptr->Echo(in, &out);
+
+ state->NextStep(); // End: EchoCall. Begin: Teardown
+
+ ZX_ASSERT(status == ZX_OK);
+ }
+
+ loop.Quit();
+ return true;
+}
+
+} // namespace hlcpp_benchmarks
+
+#endif // SRC_TESTS_BENCHMARKS_FIDL_HLCPP_ECHO_CALL_BENCHMARK_UTIL_H_
diff --git a/tools/fidl/gidl/cpp/benchmarks.go b/tools/fidl/gidl/cpp/benchmarks.go
index 2ba65f6..c8f3924 100644
--- a/tools/fidl/gidl/cpp/benchmarks.go
+++ b/tools/fidl/gidl/cpp/benchmarks.go
@@ -21,6 +21,7 @@
#include "src/tests/benchmarks/fidl/hlcpp/builder_benchmark_util.h"
#include "src/tests/benchmarks/fidl/hlcpp/decode_benchmark_util.h"
#include "src/tests/benchmarks/fidl/hlcpp/encode_benchmark_util.h"
+#include "src/tests/benchmarks/fidl/hlcpp/echo_call_benchmark_util.h"
#include "src/tests/benchmarks/fidl/hlcpp/send_event_benchmark_util.h"
namespace {
@@ -44,6 +45,11 @@
return hlcpp_benchmarks::SendEventBenchmark<{{ .EventProtocolType }}>(state, Build{{ .Name }});
}
{{- end -}}
+{{ if .EnableEchoCallBenchmark }}
+bool BenchmarkEchoCall{{ .Name }}(perftest::RepeatState* state) {
+ return hlcpp_benchmarks::EchoCallBenchmark<{{ .EchoCallProtocolType }}>(state, Build{{ .Name }});
+}
+{{- end -}}
void RegisterTests() {
perftest::RegisterTest("HLCPP/Builder/{{ .Path }}/WallTime", BenchmarkBuilder{{ .Name }});
@@ -52,6 +58,9 @@
{{ if .EnableSendEventBenchmark }}
perftest::RegisterTest("HLCPP/SendEvent/{{ .Path }}/Steps", BenchmarkSendEvent{{ .Name }});
{{- end -}}
+ {{ if .EnableEchoCallBenchmark }}
+ perftest::RegisterTest("HLCPP/EchoCall/{{ .Path }}/Steps", BenchmarkEchoCall{{ .Name }});
+ {{- end -}}
}
PERFTEST_CTOR(RegisterTests)
@@ -59,10 +68,10 @@
`))
type benchmarkTmplInput struct {
- Path, Name, Type string
- ValueBuild, ValueVar string
- EventProtocolType string
- EnableSendEventBenchmark bool
+ Path, Name, Type string
+ ValueBuild, ValueVar string
+ EventProtocolType, EchoCallProtocolType string
+ EnableSendEventBenchmark, EnableEchoCallBenchmark bool
}
// Generate generates High-Level C++ benchmarks.
@@ -88,7 +97,9 @@
ValueBuild: valueBuild,
ValueVar: valueVar,
EventProtocolType: benchmarkTypeFromValue(gidlBenchmark.Value) + "EventProtocol",
+ EchoCallProtocolType: benchmarkTypeFromValue(gidlBenchmark.Value) + "EchoCall",
EnableSendEventBenchmark: gidlBenchmark.EnableSendEventBenchmark,
+ EnableEchoCallBenchmark: gidlBenchmark.EnableEchoCallBenchmark,
}); err != nil {
return nil, err
}