blob: da3bb868937a0a04b4d9418f5920e138f5e8f34b [file] [log] [blame]
// 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/trace-provider/provider.h>
#include <zircon/syscalls.h>
#include <array>
#include "util.h"
// Measure the times taken to write and then read back a UDP packet on a
// localhost socket from a single thread using sendto() and recvfrom().
void UDPSendRecv() {
fbl::unique_fd recvfd;
FX_CHECK(recvfd = fbl::unique_fd(socket(AF_INET, SOCK_DGRAM, 0))) << strerror(errno);
struct sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
FX_CHECK(bind(recvfd.get(), reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)) == 0)
<< strerror(errno);
socklen_t addrlen = sizeof(addr);
FX_CHECK(getsockname(recvfd.get(), reinterpret_cast<struct sockaddr*>(&addr), &addrlen) == 0)
<< strerror(errno);
FX_CHECK(addrlen == sizeof(addr));
struct timeval tv = {};
tv.tv_sec = 1u;
FX_CHECK(setsockopt(recvfd.get(), SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == 0)
<< strerror(errno);
struct SizeAndTraceEventNames {
ssize_t size;
const char* send_event_name;
const char* recv_event_name;
};
#define CREATE_SIZE_AND_TRACE_EVENT_NAMES(size) \
{ size, "send_" #size "bytes", "recv_" #size "bytes" }
constexpr std::array<SizeAndTraceEventNames, 4> kSizeAndTraceEventNames = {{
CREATE_SIZE_AND_TRACE_EVENT_NAMES(64),
CREATE_SIZE_AND_TRACE_EVENT_NAMES(1024),
CREATE_SIZE_AND_TRACE_EVENT_NAMES(2048),
CREATE_SIZE_AND_TRACE_EVENT_NAMES(4096),
}};
fbl::unique_fd sendfd;
FX_CHECK(sendfd = fbl::unique_fd(socket(AF_INET, SOCK_DGRAM, 0))) << strerror(errno);
constexpr uint32_t kIterationCount = 1000;
for (const auto& [size, send_event_name, recv_event_name] : kSizeAndTraceEventNames) {
auto buf = std::make_unique<uint8_t[]>(size);
for (uint32_t i = 0; i < kIterationCount; i++) {
TraceSend(sendfd.get(), buf.get(), size, send_event_name, &addr, addrlen);
TraceRecv(recvfd.get(), buf.get(), size, recv_event_name, &addr, addrlen);
}
}
}
int main(int argc, char* argv[]) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
loop.StartThread("trace");
trace::TraceProviderWithFdio provider(loop.dispatcher());
// Wait for tracing to get set up. Without this, the tracing system can miss
// some of the initial tracing events we generate later.
//
// TODO(fxbug.dev/22911): Replace this sleep with single function that will start
// a TraceProvider in a non-racy way.
zx_nanosleep(zx_deadline_after(ZX_SEC(1)));
UDPSendRecv();
return 0;
}