4

I'm trying Linux libaio for optimized IO performance in server application. I believe I've done everything necessary (using O_DIRECT, align buffer with memory page...). I'm expecting the call to io_submit returns immediately, but a simple test showing it actually takes something around 80 micro seconds to return on my core i7 laptop. Am I expecting too much or there is something wrong with my test program? (compiled with g++ --std=c++0x -laio )

#include <unistd.h>
#include <fcntl.h>
#include <libaio.h>
#include <errno.h>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <chrono>

// Open the file for write, return the file descriptor
int open_write(char const* file)
{
  int fd = open(file, O_DIRECT|O_CREAT|O_WRONLY, S_IRWXU|S_IRWXG|S_IROTH);
  if (fd < 0) {
    perror("open_write");
    exit(1);
  }
}

// Make a buffer of _size_ byte, fill with 'a', return the buffer, it should be aligned to memory page
void* make_write_buffer(size_t size)
{
  void* buf = 0;
  int ret = posix_memalign((void**)&buf, sysconf(_SC_PAGESIZE), size);
  if (ret < 0 || buf == 0) {
    perror("make_write_buffer");
    exit(1);
  }
  memset(buf, 'a', size);
  return buf;
}

int main (int argc, char *argv[])
{    
  static const size_t SIZE = 16 * 1024;

  // Prepare file and buffer to write
  int write_fd = open_write("test.dat");
  void* buf = make_write_buffer(SIZE);

  // Prepare aio
  io_context_t ctx;
  memset(&ctx, 0, sizeof(ctx));
  const int maxEvents = 32;
  io_setup(maxEvents, &ctx);

  iocb *iocbpp = new iocb;
  io_prep_pwrite(iocbpp, write_fd, buf, SIZE, 0);

  using namespace std::chrono;
  // Submit aio task
  auto start = monotonic_clock::now();
  int status = io_submit(ctx, 1, &iocbpp);
  if (status < 0) {
    errno = -status;
    perror("io_submit");
    exit(1);
  }
  auto dur = duration_cast<microseconds>(monotonic_clock::now() - start);
  std::cout << "io_submit takes: " << dur.count() << " microseconds." << std::endl;

  io_event events[10];
  int n = io_getevents(ctx, 1, 10, events, NULL);

  close(write_fd);
  io_destroy(ctx);
  delete iocbpp;
  free(buf);
  return 0;
}
Ralph Zhang
  • 5,015
  • 5
  • 30
  • 40
  • 80 microseconds, slow? :p Best guess: your process has been scheduled. What if you increase your buffer size? – fge Dec 25 '11 at 13:07
  • Also, measure a few hundreds (or thousands) calls, timing the very first call to that function doesn't seem like a great idea. – Mat Dec 25 '11 at 13:08
  • Thanks, Mat. I did time several, 80 micro seconds is kind of average. A 'cold' operation can sometimes cost 400 micro seconds. – Ralph Zhang Dec 25 '11 at 21:36

3 Answers3

5

In short: io_submit blocks, and there's nothing you can do about it short of fixing the kernel.

Here's a "blocking io_submit" thread from 2011-09-23 on the linux-aio mailing list.

As pointed out in that thread, you could try increasing /sys/block/xxx/queue/nr_requests

Anon
  • 6,306
  • 2
  • 38
  • 56
Arvid
  • 10,915
  • 1
  • 32
  • 40
  • I tried writing like 500MB or so and it also blocked (like 3 seconds) in io_submit. Is that to be expected as well? – Marenz Feb 03 '14 at 15:27
0

How long does io_getevents take? If most of the time are spent in io_submit and not in io_getevents then the io may actually already get executed during io_submit. (In my case I suspect that's ext4s fault...)

Another thing you can try is pinning your process to a core using taskset?

Btw you can also get these timings using strace -T.

Edit: I was wrong in suspecting ext4, turns out the lack of O_DIRECT flag was causing the synchronous behaviour.

Jan Doms
  • 41
  • 3
0

As pointed out in the other answer by @Arvid, io_submit() can block. There is a non-exhaustive list of reasons why io_submit() can block over on asynchronous IO io_submit latency in Ubuntu Linux and here I'd guess that file extending writes are being performed on an ext4 filesystem thus causing io_submit() to go synchronous while filesystem metadata is written...

Anon
  • 6,306
  • 2
  • 38
  • 56