| // 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/zircon/benchmarks/cpp/fidl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/fidl/cpp/binding.h> |
| #include <lib/zx/channel.h> |
| #include <lib/zx/handle.h> |
| |
| #include <functional> |
| #include <thread> |
| #include <vector> |
| |
| #include "assert.h" |
| #include "test_runner.h" |
| |
| // This file benchmarks a common FIDL server using a libasync dispatch loop. |
| // |
| // In each benchmark iteration, a single thread enqueues N messages (the |
| // "client write" phase), and then runs an async loop to idle ("server |
| // process" phase), where each message will be handled by a null callback. |
| // |
| // The server process phase exercises Zircon's channel waiting and reading |
| // mechanisms, trivial FIDL message decoding, and the libasync dispatch loop. |
| |
| namespace { |
| |
| class NotificationImpl : public fuchsia::zircon::benchmarks::Notification { |
| public: |
| void Notify() override {} |
| }; |
| |
| bool AsyncLoopProcessBatch(uint32_t count, perftest::RepeatState* state) { |
| state->DeclareStep("client_write"); |
| state->DeclareStep("server_process"); |
| |
| // Set up client. |
| zx::channel server, client; |
| ASSERT_OK(zx::channel::create(0, &server, &client)); |
| fuchsia::zircon::benchmarks::NotificationSyncPtr service; |
| service.Bind(std::move(client)); |
| |
| // Set up server. |
| NotificationImpl service_impl; |
| async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread); |
| fidl::Binding<fuchsia::zircon::benchmarks::Notification> binding(&service_impl, |
| std::move(server)); |
| binding.set_error_handler([&loop](zx_status_t status) { loop.Quit(); }); |
| |
| // Start the benchmark. |
| while (state->KeepRunning()) { |
| // Enqueue 'count' messages. |
| for (uint32_t i = 0; i < count; i++) { |
| ASSERT_OK(service->Notify()); |
| } |
| |
| state->NextStep(); |
| |
| // Process all messages.' |
| loop.RunUntilIdle(); |
| } |
| |
| return true; |
| } |
| |
| void RegisterTests() { |
| // Return a benchmark function the processes "count" messages per batch. |
| auto AsyncLoopProcessBatchN = [](uint32_t count) { |
| return [count](perftest::RepeatState* state) { return AsyncLoopProcessBatch(count, state); }; |
| }; |
| |
| perftest::RegisterTest("AsyncLoopProcessBatch/1", AsyncLoopProcessBatchN(1)); |
| perftest::RegisterTest("AsyncLoopProcessBatch/2", AsyncLoopProcessBatchN(2)); |
| perftest::RegisterTest("AsyncLoopProcessBatch/4", AsyncLoopProcessBatchN(4)); |
| perftest::RegisterTest("AsyncLoopProcessBatch/8", AsyncLoopProcessBatchN(8)); |
| perftest::RegisterTest("AsyncLoopProcessBatch/16", AsyncLoopProcessBatchN(16)); |
| } |
| PERFTEST_CTOR(RegisterTests) |
| |
| } // namespace |