【问题标题】:Linux async IO with libaio performance issue带有 libaio 性能问题的 Linux 异步 IO
【发布时间】:2011-12-25 12:57:40
【问题描述】:

我正在尝试使用 Linux libaio 来优化服务器应用程序中的 IO 性能。我相信我已经完成了所有必要的事情(使用 O_DIRECT,将缓冲区与内存页面对齐......)。我期待对 io_submit 的调用立即返回,但一个简单的测试表明它实际上需要大约 80 微秒才能在我的核心 i7 笔记本电脑上返回。是我期望太高还是我的测试程序有问题? (用 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;
}

【问题讨论】:

  • 80 微秒,慢吗? :p 最好的猜测:你的进程已经安排好了。如果增加缓冲区大小会怎样?
  • 另外,测量数百(或数千)次调用,对第一次调用该函数的时间似乎不是一个好主意。
  • 谢谢,马特。我做了几次,平均80微秒。 “冷”操作有时会花费 400 微秒。

标签: c++ linux performance asynchronous aio


【解决方案1】:

简而言之:io_submit 阻塞,除了修复内核之外,您无能为力。

Here's a "blocking io_submit" thread from 2011-09-23 在 linux-aio 邮件列表中。

正如该线程中所指出的,您可以尝试增加/sys/block/xxx/queue/nr_requests

【讨论】:

  • 我尝试写入 500MB 左右,但它在 io_submit 中也被阻塞(如 3 秒)。这也是意料之中的吗?
【解决方案2】:

io_getevents 需要多长时间?如果大部分时间都花在 io_submit 而不是 io_getevents 中,那么 io 实际上可能已经在 io_submit 期间执行。 (就我而言,我怀疑这是 ext4s 的错……)

您可以尝试的另一件事是使用taskset 将您的进程固定到核心?

顺便说一句,您也可以使用 strace -T 获取这些时间。

编辑:我怀疑 ext4 是错误的,事实证明缺少 O_DIRECT 标志是导致同步行为的原因。

【讨论】:

    【解决方案3】:

    作为pointed out in the other answer by @Arvidio_submit() 可以阻止。 non-exhaustive list of reasons why io_submit() can blockasynchronous IO io_submit latency in Ubuntu Linux 上有一个non-exhaustive list of reasons why io_submit() can block,在这里我猜想文件扩展写入正在ext4 文件系统上执行,因此导致io_submit() 在写入文件系统元数据时同步...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-23
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      相关资源
      最近更新 更多