测试主机是AIX6.1
测试数据是向文件中顺序写入 8K * 50000 大小的数据,生成的文件大约为390M
测试对比了两种写操作,一种是aio_write, 另一种是 pwrite64; dwFlags 是open文件时,传入的参数
第一种测试
dwFlags = O_RDWR | O_LARGEFILE | O_DIRECT | O_CREAT | O_EXCL;
pwrite64 时间 : 237 秒
aio_write 时间: 236 秒
第二种测试
dwFlags = O_RDWR | O_LARGEFILE | O_SYNC | O_CREAT | O_EXCL;
pwrite64 时间 : 560秒
aio_write 时间: 567秒
第三种测试
dwFlags = O_RDWR | O_LARGEFILE | O_DIRECT | O_SYNC | O_CREAT | O_EXCL;
pwrite64 时间 : 568秒
aio_write 时间: 569秒
由于测试只是测试写操作,而且是顺序写,没有随机写;另一方面,没有在写操作中,加入写读作;还有就是只是对单一文件的写操作,不是多线程同时对多个文件的操作,所以测试还有很多局限性,更详细的测试需要进一步完成,还需测试不同页面大小时对性能的影响
从上面这三种测试来看,
第一,当 dwFlags 相同时, 在单文件上面,同步写(pwrite64 )和异步写(aio_write )差距不大,主要原因估计是glibc的底层实现也是通过pwrite64 实现的,只不过加了一个多线程,也许对多个文件时,会有一些差别。
第二,O_DIRECT 比 O_SYNC 比较大的提高写性能,快了一半,
第三,O_SYNC 与 O_DIRECT | O_SYNC 几乎相同,
下面是测试用的程序
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <aio.h>
#include <string.h>
#include <errno.h>
typedef char _aligned_char __attribute__ ((aligned (8192)));
const int DATA_LEN = 8192;
const int DATA_SIZE = 50000;
//_aligned_char bufferAO[8192];
char bufferAO[8192] __attribute__((aligned(4096)));
void testAIO()
{
struct timeval start;
struct timeval end;
int ret;
//_aligned_char buffer[DATA_LEN];
int i = 0;
struct aioinit;
int dwFlags = O_RDWR | O_LARGEFILE | O_DIRECT | O_SYNC | O_CREAT | O_EXCL; //| O_NOATIME
dwFlags = O_RDWR | O_LARGEFILE | O_SYNC | O_CREAT | O_EXCL;
//aioinit.aio_threads = 10;
//aioinit.aio_num = 10;
//aio_init(&aioinit);
int fd = open("aio_write.dat", dwFlags);
if (fd<0)
{
perror("open error:");
return;
}
if (ftruncate64(fd, DATA_LEN * DATA_SIZE))
{
perror("ftruncate64 error:");
return;
}
gettimeofday(&start, NULL);
for (; i<= DATA_SIZE; i++)
{
struct aiocb stAio;
memset(&stAio, 0, sizeof(stAio));
stAio.aio_buf = bufferAO;
stAio.aio_nbytes = DATA_LEN;
stAio.aio_offset = i * DATA_LEN;
stAio.aio_fildes = fd;
ret = aio_write(&stAio);
if(ret < 0)
{
perror("aio_write error:");
return;
}
struct aiocb *cblist[1] = {&stAio};
ret = aio_error(&stAio);
if (ret == 0) {
// already completed
}
else if (ret == EINPROGRESS) {
if (aio_suspend((const struct aiocb *const*)cblist, 1, NULL))
{
perror("aio_suspend error:");
return;
}
}
else {
perror("aio_error error:");
return;
}
if (aio_return(&stAio) != DATA_LEN)
{
perror("aio_return error:");
return;
}
}
gettimeofday(&end, NULL);
close(fd);
printf("/nAIO O_DIRECT second : %d microSec : %d/n", end.tv_sec-start.tv_sec, end.tv_usec-start.tv_usec);
}
void test()
{
struct timeval start;
struct timeval end;
int ret;
//_aligned_char buffer[DATA_LEN];
int i = 0;
int dwFlags = O_RDWR | O_LARGEFILE | O_DIRECT | O_SYNC | O_CREAT | O_EXCL; //| O_NOATIME
dwFlags = O_RDWR | O_LARGEFILE | O_SYNC | O_CREAT | O_EXCL;
int fd = open("write.dat", dwFlags);
if (fd<0)
{
perror("open error:");
return;
}
if (ftruncate64(fd, DATA_LEN * DATA_SIZE))
{
perror("ftruncate64 error:");
return;
}
gettimeofday(&start, NULL);
for (; i<= DATA_SIZE; i++)
{
//int nLen = write(fd, bufferAO, DATA_LEN);
int nLen = pwrite64(fd, bufferAO, DATA_LEN, i*DATA_LEN );
if (nLen<DATA_LEN)
{
perror("write error:");
return;
}
}
gettimeofday(&end, NULL);
close(fd);
printf("/nnoAio second : %d microSec : %d/n", end.tv_sec-start.tv_sec, end.tv_usec-start.tv_usec);
}
int main()
{
test();
testAIO();
return 1;
}