github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/test/perf/linux/epoll_benchmark.cc (about)

     1  // Copyright 2020 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include <sys/epoll.h>
    16  #include <sys/eventfd.h>
    17  
    18  #include <atomic>
    19  #include <cerrno>
    20  #include <cstdint>
    21  #include <cstdlib>
    22  #include <ctime>
    23  #include <memory>
    24  
    25  #include "gtest/gtest.h"
    26  #include "absl/time/time.h"
    27  #include "benchmark/benchmark.h"
    28  #include "test/util/epoll_util.h"
    29  #include "test/util/file_descriptor.h"
    30  #include "test/util/test_util.h"
    31  #include "test/util/thread_util.h"
    32  
    33  namespace gvisor {
    34  namespace testing {
    35  
    36  namespace {
    37  
    38  // Returns a new eventfd.
    39  PosixErrorOr<FileDescriptor> NewEventFD() {
    40    int fd = eventfd(0, /* flags = */ 0);
    41    MaybeSave();
    42    if (fd < 0) {
    43      return PosixError(errno, "eventfd");
    44    }
    45    return FileDescriptor(fd);
    46  }
    47  
    48  // Also stolen from epoll.cc unit tests.
    49  void BM_EpollTimeout(benchmark::State& state) {
    50    constexpr int kFDsPerEpoll = 3;
    51    auto epollfd = ASSERT_NO_ERRNO_AND_VALUE(NewEpollFD());
    52  
    53    std::vector<FileDescriptor> eventfds;
    54    for (int i = 0; i < kFDsPerEpoll; i++) {
    55      eventfds.push_back(ASSERT_NO_ERRNO_AND_VALUE(NewEventFD()));
    56      ASSERT_NO_ERRNO(
    57          RegisterEpollFD(epollfd.get(), eventfds[i].get(), EPOLLIN, 0));
    58    }
    59  
    60    struct epoll_event result[kFDsPerEpoll];
    61    int timeout_ms = state.range(0);
    62  
    63    for (auto _ : state) {
    64      EXPECT_EQ(0, epoll_wait(epollfd.get(), result, kFDsPerEpoll, timeout_ms));
    65    }
    66  }
    67  
    68  BENCHMARK(BM_EpollTimeout)->Range(0, 8);
    69  
    70  // Also stolen from epoll.cc unit tests.
    71  void BM_EpollAllEvents(benchmark::State& state) {
    72    auto epollfd = ASSERT_NO_ERRNO_AND_VALUE(NewEpollFD());
    73    const int fds_per_epoll = state.range(0);
    74    constexpr uint64_t kEventVal = 5;
    75  
    76    std::vector<FileDescriptor> eventfds;
    77    for (int i = 0; i < fds_per_epoll; i++) {
    78      eventfds.push_back(ASSERT_NO_ERRNO_AND_VALUE(NewEventFD()));
    79      ASSERT_NO_ERRNO(
    80          RegisterEpollFD(epollfd.get(), eventfds[i].get(), EPOLLIN, 0));
    81  
    82      ASSERT_THAT(WriteFd(eventfds[i].get(), &kEventVal, sizeof(kEventVal)),
    83                  SyscallSucceedsWithValue(sizeof(kEventVal)));
    84    }
    85  
    86    std::vector<struct epoll_event> result(fds_per_epoll);
    87  
    88    for (auto _ : state) {
    89      EXPECT_EQ(fds_per_epoll,
    90                epoll_wait(epollfd.get(), result.data(), fds_per_epoll, 0));
    91    }
    92  }
    93  
    94  BENCHMARK(BM_EpollAllEvents)->Range(2, 1024);
    95  
    96  }  // namespace
    97  
    98  }  // namespace testing
    99  }  // namespace gvisor