2011-12-25 86 views
4

我正在尝试Linux libaio以在服务器应用程序中优化IO性能。我相信我已经做了所有必要的事情(使用O_DIRECT,将缓冲区与内存页面对齐...)。我在等待io_submit立即返回,但一个简单的测试显示它实际上需要80微秒左右的时间才能在我的核心i7笔记本电脑上返回。我是否期望过多或者测试计划有问题? (编译G ++ --std =的C++ 0x -laio)具有libaio性能问题的Linux异步IO

#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; 
} 
+0

80微秒,慢? :p最佳猜想:你的过程已经安排完毕。如果你增加你的缓冲区大小呢? – fge 2011-12-25 13:07:38

+0

另外,测量几百(或几千)个调用,对该函数的第一次调用进行计时似乎不是一个好主意。 – Mat 2011-12-25 13:08:37

+0

谢谢,马特。我做了几次,80微秒是平均水平。 “冷”操作有时可能需要400微秒。 – 2011-12-25 21:36:25

回答

4

简而言之:io_submit块,并没有什么,你可以做短固定的内核。

here是kernel-aio的一个线程。

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

+0

我试图写入500MB左右,并且它也在io_submit中封锁(如3秒)。这也是预料之中吗? – Marenz 2014-02-03 15:27:07

0

多久io_getevents走?如果大部分时间都用于io_submit而不是io_getevents,那么在io_submit期间,io实际上可能已经被执行。 (在我的情况下,我怀疑这是ext4s故障...)

你可以尝试的另一件事是固定你的过程到核心使用taskset

顺便说一句,你也可以使用strace -T得到这些时间。

编辑:我怀疑是在怀疑ext4,结果是缺乏O_DIRECT标志导致了同步行为。