Commit 7fb9e296 authored by Florian Fischer's avatar Florian Fischer
Browse files

add linux_aio implementation and read instead of write the eventfd

parent 466cb9f8
Pipeline #66573 failed with stage
in 1 minute and 29 seconds
BENCH_MAIN := bench.c
SYSCALLS := blocking io_uring io_uring_sqpoll io_uring_no_syscall epoll paio_sig paio_thrd
SYSCALLS := blocking io_uring io_uring_sqpoll io_uring_no_syscall epoll paio_sig paio_thrd linux_aio
OBJ := $(addprefix bench-,$(SYSCALLS))
LDFLAGS := -luring -pthread -lrt -lm
LDFLAGS := -luring -pthread -lrt -lm -laio
CFLAGS := -Werror -Wall -g -O3
# CFLAGS := -Werror -Wall -g -O0
......
#include <err.h>
#include <fcntl.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
......@@ -11,15 +12,15 @@
#include "stopwatch.h"
void init(int fd);
void do_write(int fd, const void *buf, size_t count);
void do_read(int fd, void *buf, size_t count);
size_t warmup = 10000;
size_t iterations = 1000000;
unsigned warmup = 10000;
unsigned iterations = 1000000;
#define BUFSIZE 64
static int create_eventfd() {
int fd = eventfd(0, 0);
int fd = eventfd(UINT_MAX, EFD_SEMAPHORE);
if (fd == -1) {
err(EXIT_FAILURE, "eventfd failed");
}
......@@ -31,24 +32,24 @@ int main(int argc, char *argv[]) {
if (argc > 2 || (argc == 2 && !(print_stats = (strcmp(argv[1], "--stats") == 0))))
errx(EXIT_SUCCESS, "Usage: %s [--stats]", argv[0]);
uint64_t write_buf = 1;
uint64_t read_buf = 1;
int fd = create_eventfd();
init(fd);
const size_t exp_warmup = warmup;
const size_t exp_iterations = iterations;
const unsigned exp_warmup = warmup;
const unsigned exp_iterations = iterations;
if (exp_iterations == 0) errx(EXIT_FAILURE, "experiment must do at least one iteration");
uint64_t *nanos = malloc(exp_iterations * sizeof(uint64_t));
uint64_t *cycles = malloc(exp_iterations * sizeof(uint64_t));
if (!nanos || !cycles) err(EXIT_FAILURE, "allocating memory for our results failed");
if (exp_iterations == 0) errx(EXIT_FAILURE, "experiment must do at least one iteration");
for (size_t i = 0; i < exp_warmup; ++i) do_write(fd, &write_buf, sizeof(write_buf));
for (unsigned i = 0; i < exp_warmup; ++i) do_read(fd, &read_buf, sizeof(read_buf));
for (int64_t i = 1; i <= exp_iterations; ++i) {
do_write(fd, &write_buf, sizeof(write_buf));
for (unsigned i = 1; i <= exp_iterations; ++i) {
do_read(fd, &read_buf, sizeof(read_buf));
nanos[i - 1] = clock_diff_nanos();
cycles[i - 1] = clock_diff_cycles();
}
......
......@@ -6,10 +6,10 @@
void init(__attribute__((unused)) int fd) {}
void do_write(int fd, const void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
start_watch();
ssize_t res = write(fd, buf, count);
ssize_t res = read(fd, buf, count);
stop_watch();
if (res == -1) err(EXIT_FAILURE, "write failed");
if (res == -1) err(EXIT_FAILURE, "read failed");
}
......@@ -3,4 +3,4 @@
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
extern size_t warmup, iterations;
extern unsigned warmup, iterations;
......@@ -12,21 +12,21 @@ void init(int fd) {
epollfd = epoll_create1(0);
if (epollfd == -1) err(EXIT_FAILURE, "creating epoll failed");
ev.events = EPOLLOUT;
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) err(EXIT_FAILURE, "epoll_ctl failed");
}
void do_write(int fd, const void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
start_watch();
nfds = epoll_wait(epollfd, &ev, 1, -1);
size_t res = write(fd, buf, count);
size_t res = read(fd, buf, count);
stop_watch();
if (nfds == -1) err(EXIT_FAILURE, "epoll_wait failed");
if (ev.data.fd != fd) errx(EXIT_FAILURE, "got unexpected fd from epoll");
if (res == -1) err(EXIT_FAILURE, "write failed");
if (res == -1) err(EXIT_FAILURE, "read failed");
}
......@@ -15,11 +15,11 @@ void init(__attribute__((unused)) int fd) {
}
}
void do_write(int fd, const void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
start_watch();
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_write(sqe, fd, buf, count, 0);
io_uring_prep_read(sqe, fd, buf, count, 0);
int res = io_uring_submit_and_wait(&ring, 1);
......@@ -31,5 +31,5 @@ void do_write(int fd, const void *buf, size_t count) {
res = io_uring_peek_cqe(&ring, &cqe);
if (res < 0) err(EXIT_FAILURE, "io_uring_peek_cqe failed");
if (cqe->res < 0) err(EXIT_FAILURE, "write request failed");
if (cqe->res < 0) err(EXIT_FAILURE, "read request failed");
}
......@@ -11,9 +11,9 @@ struct io_uring ring;
void init(__attribute__((unused)) int fd) { io_uring_init_sqpoll(&ring); }
void do_write(int fd, const void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
struct io_uring_sqe *sqe = sqpoll_ring_get_sqe(&ring);
io_uring_prep_write(sqe, fd, buf, count, 0);
io_uring_prep_read(sqe, fd, buf, count, 0);
start_watch();
int res = io_uring_submit(&ring);
......@@ -26,5 +26,5 @@ void do_write(int fd, const void *buf, size_t count) {
if (res < 0) err(EXIT_FAILURE, "io_submit failed");
if (cqe->res < 0) err(EXIT_FAILURE, "write request failed");
if (cqe->res < 0) err(EXIT_FAILURE, "read request failed");
}
......@@ -11,9 +11,9 @@ struct io_uring ring;
void init(__attribute__((unused)) int fd) { io_uring_init_sqpoll(&ring); }
void do_write(int fd, const void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
struct io_uring_sqe *sqe = sqpoll_ring_get_sqe(&ring);
io_uring_prep_write(sqe, fd, buf, count, 0);
io_uring_prep_read(sqe, fd, buf, count, 0);
start_watch();
int res = io_uring_submit_and_wait(&ring, 1);
......@@ -28,5 +28,5 @@ void do_write(int fd, const void *buf, size_t count) {
if (res < 0) err(EXIT_FAILURE, "io_uring_peek_cqe failed");
if (cqe->res < 0) err(EXIT_FAILURE, "write request failed");
if (cqe->res < 0) err(EXIT_FAILURE, "read request failed");
}
#include <err.h>
#include <errno.h>
#include <libaio.h>
#include <stdlib.h>
#include "common.h"
#include "stopwatch.h"
io_context_t ctx;
void init(__attribute__((unused)) int fd) {
int res = io_queue_init(1, &ctx);
if (res < 0) {
errno = -res;
err(EXIT_FAILURE, "io_queue_setup failed");
}
}
void do_read(int fd, const void *buf, size_t count) {
struct io_event ev;
struct iocb io;
struct iocb *ioq[] = {&io};
io_prep_pread(&io, fd, (void *)buf, count, 0);
start_watch();
int s_res = io_submit(ctx, 1, ioq);
if (unlikely(s_res < 0)) {
errno = -s_res;
err(EXIT_FAILURE, "io_submit failed");
}
int w_res = io_getevents(ctx, 1, 1, &ev, NULL);
stop_watch();
if (w_res < 0) err(EXIT_FAILURE, "io_getevents failed");
if (ev.res2 != 0) err(EXIT_FAILURE, "read request failed");
}
......@@ -31,14 +31,14 @@ void init(int fd) {
if (sigaction(SIGUSR1, &sa, NULL) == -1) err(EXIT_FAILURE, "sigaction failed");
}
void do_write(int fd, const void *buf, size_t count) {
aiocb.aio_buf = (void *)buf;
void do_read(int fd, void *buf, size_t count) {
aiocb.aio_buf = buf;
aiocb.aio_nbytes = count;
start_watch();
int res = aio_write(&aiocb);
int res = aio_read(&aiocb);
if (unlikely(res == -1)) err(EXIT_FAILURE, "aio_write failed");
if (unlikely(res == -1)) err(EXIT_FAILURE, "aio_read failed");
while (!atomic_load(&done)) {
}
......
......@@ -29,16 +29,16 @@ void init(int fd) {
aiocb.aio_sigevent.sigev_value.sival_int = 42;
}
void do_write(int fd, void *buf, size_t count) {
void do_read(int fd, void *buf, size_t count) {
aiocb.aio_buf = buf;
aiocb.aio_nbytes = count;
start_watch();
int res = aio_write(&aiocb);
int res = aio_read(&aiocb);
while (!atomic_load(&done)) {
}
atomic_store(&done, 0);
if (res == -1) err(EXIT_FAILURE, "aio_write failed");
if (res == -1) err(EXIT_FAILURE, "aio_read failed");
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment