Linux асинхронный ввод-вывод с проблемой производительности libaio - PullRequest
4 голосов
/ 25 декабря 2011

Я пробую Linux libaio для оптимизации производительности ввода-вывода в серверном приложении. Я считаю, что я сделал все необходимое (используя O_DIRECT, выровняйте буфер со страницей памяти ...). Я ожидаю, что вызов io_submit немедленно вернется, но простой тест, показывающий, что на моем ядре i7 требуется около 80 микросекунд. Я ожидаю слишком многого или что-то не так с моей тестовой программой? (скомпилировано с 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;
}

Ответы [ 2 ]

5 голосов
/ 28 декабря 2011

Короче говоря: io_submit блокирует, и вы ничего не можете с этим поделать, кроме как исправить ядро.

здесь поток от kernel-aio.1007 * Как указано в этой теме, вы можете попробовать увеличить /sys/block/xxx/queue/nr_requests

0 голосов
/ 02 апреля 2016

Сколько времени займет io_getevents?Если большую часть времени проводят в io_submit, а не в io_getevents, то io может фактически уже выполняться во время io_submit.(В моем случае я подозреваю, что это ошибка ext4s ...)

Другая вещь, которую вы можете попробовать, это закрепить ваш процесс на ядре, используя taskset?

Кстати, вы также можете получить эти тайминги, используяstrace -T.

Редактировать: я ошибся в подозрении на ext4, оказывается, отсутствие флага O_DIRECT вызывало синхронное поведение.

...