blob: 2efca1f51a4c3a27534c9bd5264365ecf7fcf2d8 [file] [log] [blame]
// Copyright 2022 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_DRIVER_LLCPP_ECHO_CALL_SYNC_BENCHMARK_UTIL_H_
#define SRC_TESTS_BENCHMARKS_FIDL_DRIVER_LLCPP_ECHO_CALL_SYNC_BENCHMARK_UTIL_H_
#include <lib/async/cpp/task.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/fdf/dispatcher.h>
#include <lib/fdf/internal.h>
#include <lib/fidl_driver/cpp/wire_messaging.h>
#include <lib/fit/defer.h>
#include <lib/sync/cpp/completion.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <perftest/perftest.h>
namespace driver_benchmarks {
template <typename ProtocolType, typename FidlType>
class EchoServerSyncImpl : public fdf::WireServer<ProtocolType> {
void Echo(typename fdf::WireServer<ProtocolType>::EchoRequestView request, fdf::Arena& arena,
typename fdf::WireServer<ProtocolType>::EchoCompleter::Sync& completer) override {
completer.buffer(arena).Reply(std::move(request->val));
}
};
template <typename ProtocolType, typename BuilderFunc>
bool EchoCallSyncBenchmark(perftest::RepeatState* state, BuilderFunc builder) {
using FidlType = std::invoke_result_t<BuilderFunc, fidl::AnyArena&>;
static_assert(fidl::IsFidlType<FidlType>::value, "FIDL type required");
state->DeclareStep("Setup/WallTime");
state->DeclareStep("EchoCall/WallTime");
state->DeclareStep("Teardown/WallTime");
void* driver = reinterpret_cast<void*>(uintptr_t(1));
fdf_internal_push_driver(driver);
auto deferred = fit::defer([]() { fdf_internal_pop_driver(); });
libsync::Completion client_dispatcher_shutdown;
auto client_dispatcher = fdf::Dispatcher::Create(
FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS,
[&](fdf_dispatcher_t* dispatcher) { client_dispatcher_shutdown.Signal(); });
ZX_ASSERT(ZX_OK == client_dispatcher.status_value());
libsync::Completion server_dispatcher_shutdown;
auto server_dispatcher = fdf::Dispatcher::Create(
FDF_DISPATCHER_OPTION_ALLOW_SYNC_CALLS,
[&](fdf_dispatcher_t* dispatcher) { server_dispatcher_shutdown.Signal(); });
ZX_ASSERT(ZX_OK == server_dispatcher.status_value());
auto channels = fdf::ChannelPair::Create(0);
ZX_ASSERT(ZX_OK == channels.status_value());
fdf::ServerEnd<ProtocolType> server_end(std::move(channels->end0));
fdf::ClientEnd<ProtocolType> client_end(std::move(channels->end1));
EchoServerSyncImpl<ProtocolType, FidlType> server;
fdf::ServerBindingRef binding_ref =
fdf::BindServer(server_dispatcher->get(), std::move(server_end), &server);
typename fdf::WireSyncClient<ProtocolType> client(std::move(client_end));
sync_completion_t completion;
auto run_on_dispatcher_thread = [&] {
while (state->KeepRunning()) {
fidl::Arena<65536> fidl_arena;
FidlType aligned_value = builder(fidl_arena);
auto arena = fdf::Arena::Create(0, "");
ZX_ASSERT(arena.is_ok());
state->NextStep(); // End: Setup. Begin: EchoCall.
auto result = client.buffer(*arena)->Echo(std::move(aligned_value));
state->NextStep(); // End: EchoCall. Begin: Teardown
ZX_ASSERT(result.ok());
}
// TODO(fxbug.dev/92489): If this call and wait is removed, the test will
// flake by leaking |AsyncServerBinding| objects.
binding_ref.Unbind();
sync_completion_signal(&completion);
};
async::PostTask(client_dispatcher->async_dispatcher(), run_on_dispatcher_thread);
sync_completion_wait(&completion, ZX_TIME_INFINITE);
client_dispatcher->ShutdownAsync();
server_dispatcher->ShutdownAsync();
ZX_ASSERT(ZX_OK == client_dispatcher_shutdown.Wait());
ZX_ASSERT(ZX_OK == server_dispatcher_shutdown.Wait());
return true;
}
} // namespace driver_benchmarks
#endif // SRC_TESTS_BENCHMARKS_FIDL_DRIVER_LLCPP_ECHO_CALL_SYNC_BENCHMARK_UTIL_H_