2011-12-25 6 views
4

私はサーバーアプリケーションのIOパフォーマンスを最適化するためにLinux libaioを試しています。私はすべてを必要としていると信じています(O_DIRECTを使用し、バッファをメモリページと整列させて...)。私はio_submitへの呼び出しがすぐに戻ると期待していますが、それを示す単純なテストでは、コアi7ラップトップに戻るのにおよそ80マイクロ秒かかります。あまり期待していますか、テストプログラムに何か問題がありますか? io_submitブロックを、そしてあなたがカーネルを固定する短いそれについてできることは何もありません。要するにlibaioパフォーマンスの問題を伴うLinux async 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

+0

また、数百(または千)の呼び出しを測定します。その関数の最初の呼び出しは素晴らしい考えではありません。 – Mat

+0

ありがとう、マット。私はいくつかの時間をした、80マイクロ秒は平均の一種です。 「冷たい」操作は400マイクロ秒かかることがあります。 –

答えて

4

(G ++ --std = C++ 0xの-laioでコンパイルしました)。

hereさんのkernel-aioのスレッドです。

としては、そのスレッドで指摘、あなたはio_geteventsはどのくらいかかりますか?/sys/block/xxx/queue/nr_requests

+0

私は500MBほどの書き込みを試みましたが、io_submitでブロックされました(3秒間など)。それも期待されていますか? – Marenz

0

を増やしてみてくださいほとんどの時間がio_submitに費やされていて、io_geteventsにない場合、ioは実際にはio_submitの間にすでに実行されているかもしれません。 (私の場合、ext4sの欠陥と思われます...)

もう1つのことは、tasksetを使用してプロセスをコアに固定することです。

btwまた、strace -Tを使用してこれらのタイミングを取得することもできます。

編集:私はext4の疑いで間違っていましたが、O_DIRECTフラグの欠如が同期動作を引き起こしていました。

関連する問題