首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >aio_write比普通的ext4写要花更多的时间?

aio_write比普通的ext4写要花更多的时间?
EN

Stack Overflow用户
提问于 2015-01-27 12:04:54
回答 1查看 286关注 0票数 3

我有一个C程序,它可以编写32768个块,每个块都是16K大小(总大小为512 an ),用于运行3.18.1内核的系统上的ext4文件系统。这个程序的常规写系统调用版本需要5.35秒才能完成写操作(根据for循环前后的gettimeofday度量)。但是,这个程序的异步版本需要花费以下时间:

  1. 对所有aio_writes (32768 Aio_writes)进行排队:7.43秒
  2. 轮询以完成每个IO请求:额外4.93秒

输出文件用以下flags:O_WRONLY、O_CREAT、O_NONBLOCK打开

为什么异步花费的时间比写()时间多一倍?甚至Time-to-queue-async-io-request/time-to-write-sync-io也是1.4。

由于有些人将其标记为“主题”,我查看了定义并决定粘贴代码--这似乎是应该将其标记为“主题”的唯一原因。我不是问为什么代码不能工作,而是为什么aio比常规写入慢得多,特别是因为所有并行写入都是针对不同的块的。这是aio代码,后面是非aio代码:

AIO程序

代码语言:javascript
复制
#define MAX_AIO        (16384*2)
#define BUFSIZE        16384

struct mys {
    int status;
    struct aiocb aio;
};

void set_aiocb(struct mys *aio, int num, int fd)
{
    int i;

    for (i = 0; i < num; i++) {
        aio[i].aio.aio_fildes = fd;
        aio[i].aio.aio_offset = BUFSIZE * i;
        aio[i].aio.aio_buf = malloc(BUFSIZE);
        set_buf(aio[i].aio.aio_buf, BUFSIZE, i);
        aio[i].aio.aio_nbytes = BUFSIZE;
        aio[i].aio.aio_reqprio = fd;
        aio[i].aio.aio_sigevent.sigev_notify = SIGEV_NONE;
        aio[i].aio.aio_sigevent.sigev_signo = SIGUSR1;
        aio[i].aio.aio_sigevent.sigev_value.sival_ptr = &aio[i];
        aio[i].aio.aio_lio_opcode = 0;
        aio[i].status = EINPROGRESS;
    }
}

void main(void)
{
    int fd = open("/tmp/AIO", O_WRONLY | O_CREAT, 0666);
    int i, open_reqs = MAX_AIO;
    struct mys aio[MAX_AIO];
    struct timeval start, end, diff;

    set_aiocb(aio, MAX_AIO, fd);

    gettimeofday(&start, NULL);
    for (i = 0; i < MAX_AIO; i++)
        aio_write(&aio[i].aio);

    while (open_reqs > 0) {
        for (i = 0; i < MAX_AIO; i++) {
            if (aio[i].status == EINPROGRESS) {
                aio[i].status = aio_error(&(aio[i].aio));
                if (aio[i].status != EINPROGRESS)
                    open_reqs--;
            }
        }
    }
    gettimeofday(&end, NULL);
    timersub(&end, &start, &diff);
    printf("%d.%d\n", (int)diff.tv_sec, (int)diff.tv_usec);
}

规则IO程序

代码语言:javascript
复制
#define MAX_AIO        (16384*2)
#define BUFSIZE        16384

char buf[MAX_AIO][BUFSIZE];
void main(void)
{
    int i, fd = open("/tmp/NON_AIO", O_WRONLY | O_CREAT, 0666);
    struct timeval start, end, diff;

    gettimeofday(&start, NULL);
    for (i = 0; i < MAX_AIO; i++)
        write(fd, buf[i], BUFSIZE);
    gettimeofday(&end, NULL);
    timersub(&end, &start, &diff);
    printf("%d.%d\n", (int)diff.tv_sec, (int)diff.tv_usec);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-18 03:41:29

你不是真的拿苹果和苹果作比较。

在AIO代码中,每个写操作都有一个单独分配的缓冲区,因此程序分配了512个MiB (16 * 16 *2 KiB)内存,再加上32 K的AIO控制结构副本。必须分配并初始化该内存(如果没有显示的set_buf()函数将缓冲区的每个字节设置为第三个参数的值,则每个缓冲区得到不同的值),然后由内核复制到驱动程序,可能是通过内核缓冲池。

在常规IO代码中,有一个大的连续缓冲区,它被初始化为写入磁盘的所有零。

为了使比较公平,您应该在两个程序中使用相同的基础结构,创建AIO结构,但是常规IO代码将简单地遍历结构,编写每个程序的数据部分(而AIO代码的行为大致如所示)。我希望你会发现,当你这样做的时候,你的表现会更加相似。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28170110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档