io_uring timeout testing

blocking-uring-test
Vitaliy Filippov 2019-11-17 17:45:39 +03:00
parent eec1c35ea4
commit 2f429b17dd
3 changed files with 80 additions and 12 deletions

View File

@ -17,6 +17,7 @@ ring_loop_t::ring_loop_t(int qd)
ring_loop_t::~ring_loop_t() ring_loop_t::~ring_loop_t()
{ {
free(ring_data); free(ring_data);
io_uring_queue_exit(&ring);
} }
struct io_uring_sqe* ring_loop_t::get_sqe() struct io_uring_sqe* ring_loop_t::get_sqe()
@ -47,11 +48,7 @@ void ring_loop_t::unregister_consumer(int number)
void ring_loop_t::loop(bool sleep) void ring_loop_t::loop(bool sleep)
{ {
struct io_uring_cqe *cqe; struct io_uring_cqe *cqe;
if (sleep) while (!io_uring_peek_cqe(&ring, &cqe))
{
io_uring_wait_cqe(&ring, &cqe);
}
while ((io_uring_peek_cqe(&ring, &cqe), cqe))
{ {
struct ring_data_t *d = (struct ring_data_t*)cqe->user_data; struct ring_data_t *d = (struct ring_data_t*)cqe->user_data;
if (d->callback) if (d->callback)
@ -64,4 +61,8 @@ void ring_loop_t::loop(bool sleep)
{ {
consumers[i].loop(); consumers[i].loop();
} }
if (sleep)
{
io_uring_wait_cqe(&ring, &cqe);
}
} }

View File

@ -38,7 +38,7 @@ static void test_write(struct io_uring *ring, int fd)
uint8_t *buf = (uint8_t*)memalign(512, 1024*1024*1024); uint8_t *buf = (uint8_t*)memalign(512, 1024*1024*1024);
struct iovec iov = { buf, 1024*1024*1024 }; struct iovec iov = { buf, 1024*1024*1024 };
io_uring_prep_writev(sqe, fd, &iov, 1, 0); io_uring_prep_writev(sqe, fd, &iov, 1, 0);
io_uring_sqe_set_data(sqe, 0); io_uring_sqe_set_data(sqe, buf);
io_uring_submit_and_wait(ring, 1); io_uring_submit_and_wait(ring, 1);
struct io_uring_cqe *cqe; struct io_uring_cqe *cqe;
io_uring_peek_cqe(ring, &cqe); io_uring_peek_cqe(ring, &cqe);
@ -47,7 +47,7 @@ static void test_write(struct io_uring *ring, int fd)
if (ret < 0) if (ret < 0)
printf("cqe failed: %d %s\n", ret, strerror(-ret)); printf("cqe failed: %d %s\n", ret, strerror(-ret));
else else
printf("result: %d\n", ret); printf("result: %d user_data: %d -> %d\n", ret, sqe->user_data, cqe->user_data);
io_uring_cqe_seen(ring, cqe); io_uring_cqe_seen(ring, cqe);
free(buf); free(buf);
} }
@ -70,7 +70,7 @@ inline bool operator == (const obj_ver_id & a, const obj_ver_id & b)
return a.oid == b.oid && a.version == b.version; return a.oid == b.oid && a.version == b.version;
} }
int main(int argc, char *argv[]) int main00(int argc, char *argv[])
{ {
// queue with random removal: vector is best :D // queue with random removal: vector is best :D
// deque: 8.1s // deque: 8.1s
@ -208,7 +208,7 @@ int main1(int argc, char *argv[])
return 0; return 0;
} }
int main2(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
std::map<int, std::string> strs; std::map<int, std::string> strs;
strs.emplace(12, "str"); strs.emplace(12, "str");
@ -217,7 +217,7 @@ int main2(int argc, char *argv[])
it--; it--;
printf("s = %d %s\n", it->first, it->second.c_str()); printf("s = %d %s\n", it->first, it->second.c_str());
struct io_uring ring; struct io_uring ring;
int fd = open("testfile", O_RDWR | O_DIRECT, 0644); int fd = open("/dev/loop0", O_RDWR | O_DIRECT, 0644);
if (fd < 0) if (fd < 0)
{ {
perror("open infile"); perror("open infile");

View File

@ -1,6 +1,67 @@
#include <sys/timerfd.h>
#include <sys/poll.h>
#include <iostream> #include <iostream>
#include "blockstore.h" #include "blockstore.h"
class timerfd_interval
{
int wait_state;
int timerfd;
int status;
ring_loop_t *ringloop;
ring_consumer_t consumer;
public:
timerfd_interval(ring_loop_t *ringloop, int seconds)
{
wait_state = 0;
timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if (timerfd < 0)
{
throw std::runtime_error(std::string("timerfd_create: ") + strerror(errno));
}
struct itimerspec exp = {
.it_interval = { seconds, 0 },
.it_value = { seconds, 0 },
};
if (timerfd_settime(timerfd, 0, &exp, NULL))
{
throw std::runtime_error(std::string("timerfd_settime: ") + strerror(errno));
}
consumer.loop = [this]() { loop(); };
ringloop->register_consumer(consumer);
this->ringloop = ringloop;
}
~timerfd_interval()
{
ringloop->unregister_consumer(consumer.number);
close(timerfd);
}
void loop()
{
if (wait_state == 1)
{
return;
}
struct io_uring_sqe *sqe = ringloop->get_sqe();
if (!sqe)
{
wait_state = 0;
return;
}
struct ring_data_t *data = ((ring_data_t*)sqe->user_data);
io_uring_prep_poll_add(sqe, timerfd, POLLIN);
data->callback = [&](ring_data_t *data)
{
wait_state = 0;
printf("tick\n");
};
wait_state = 1;
ringloop->submit();
}
};
int main(int narg, char *args[]) int main(int narg, char *args[])
{ {
spp::sparse_hash_map<std::string, std::string> config; spp::sparse_hash_map<std::string, std::string> config;
@ -8,9 +69,15 @@ int main(int narg, char *args[])
config["journal_device"] = "./test_journal.bin"; config["journal_device"] = "./test_journal.bin";
config["data_device"] = "./test_data.bin"; config["data_device"] = "./test_data.bin";
ring_loop_t *ringloop = new ring_loop_t(512); ring_loop_t *ringloop = new ring_loop_t(512);
blockstore *bs = new blockstore(config, ringloop); // print "tick" each second
timerfd_interval tick_tfd(ringloop, 1);
while (true)
{
ringloop->loop(true);
}
//blockstore *bs = new blockstore(config, ringloop);
delete bs; //delete bs;
delete ringloop; delete ringloop;
return 0; return 0;
} }