我有一个C程序,它可以编写32768个块,每个块都是16K大小(总大小为512 an ),用于运行3.18.1内核的系统上的ext4文件系统。这个程序的常规写系统调用版本需要5.35秒才能完成写操作(根据for循环前后的gettimeofday度量)。但是,这个程序的异步版本需要花费以下时间:
输出文件用以下flags:O_WRONLY、O_CREAT、O_NONBLOCK打开
为什么异步花费的时间比写()时间多一倍?甚至Time-to-queue-async-io-request/time-to-write-sync-io也是1.4。
由于有些人将其标记为“主题”,我查看了定义并决定粘贴代码--这似乎是应该将其标记为“主题”的唯一原因。我不是问为什么代码不能工作,而是为什么aio比常规写入慢得多,特别是因为所有并行写入都是针对不同的块的。这是aio代码,后面是非aio代码:
AIO程序
#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程序
#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);
}发布于 2015-03-18 03:41:29
你不是真的拿苹果和苹果作比较。
在AIO代码中,每个写操作都有一个单独分配的缓冲区,因此程序分配了512个MiB (16 * 16 *2 KiB)内存,再加上32 K的AIO控制结构副本。必须分配并初始化该内存(如果没有显示的set_buf()函数将缓冲区的每个字节设置为第三个参数的值,则每个缓冲区得到不同的值),然后由内核复制到驱动程序,可能是通过内核缓冲池。
在常规IO代码中,有一个大的连续缓冲区,它被初始化为写入磁盘的所有零。
为了使比较公平,您应该在两个程序中使用相同的基础结构,创建AIO结构,但是常规IO代码将简单地遍历结构,编写每个程序的数据部分(而AIO代码的行为大致如所示)。我希望你会发现,当你这样做的时候,你的表现会更加相似。
https://stackoverflow.com/questions/28170110
复制相似问题