linux 提高文件读写速度 mmap,Linux下读写速度测试

一. 文件一次读入速度

linux下读文件这东西最后都是要通过系统调用sys_read(fd,buf,count)来实现的,所以如果要提高速度,就是最简单地调用sys_read的封装,比如直接用read()或fread()。下面是我在linux下的几个测试。

首先创建一个130M数据文件 dd if=/dev/zero of=data bs=1024k count=130

分别用fread,read和fgets一次读入全部大小文件所消耗时间对比,其中

size=130*1024*1024

char *buf=new char[size];

下面是测试结果(机器Intel(R) Pentium(R) 4 CPU 3.20GHz, Mem 1G):

1.fread(buf,size,1,fp)一次读入

real    0m0.187s

user    0m0.000s

sys     0m0.180s

2.read(fdin,(void *)buf,size)一次读入

real    0m0.187s

user    0m0.000s

sys     0m0.184s

3.多次fgets(buf,size,fp),每次1k

real    0m0.356s

user    0m0.136s

sys     0m0.220s

4.fgets(buf,size,fp)一次读入

real    0m0.305s

user    0m0.072s

sys     0m0.232s

上面看到越简单的函数(read()和fread()),速度越快,其他的输入封装函数只不过是为了方便满足特殊需要,并不见得读的速度会很快。对于3和4,因为在sys_read()内部有对读入大小的判断和while循环,所以大文件读取也没必要像3那样分多次调用fgets()来读文件.

另外用mmap()内存映射来读入文件的时间如下:

real    0m0.231s

user    0m0.068s

sys     0m0.164s

也并没有比直接read()快,网上找到一种解释是对于需要频繁读写操作的,mmap效率才会显著提高。下面来模拟频繁读写操作。

二. 文件频繁读写速度测试

1. 这一个测试模拟频繁文件读写操作,500M大小的数据文件data.in,每次从中读入1k个字节对每个字节做加1简单计算,再写到另一个文件data.out中。

//mmapx1.c

#define size 1024*1024*500

#define LEN 1024

#include

int main()

{

FILE *fp1,*fp2;

char *buf=new char[LEN];

int i,j;

fp1=fopen("data.in","rb");

fp2=fopen("data.out","wb");

for(j=0;j<1024*500;j++)

{

fread(buf,1024,1,fp1);

for(i=0;i

buf[i]++;

fwrite(buf,LEN,1,fp2);

}

printf("ok!\n");

fclose(fp1);

fclose(fp2);

}

time 命令测试时间,每次结果都不一样,机器负载有关。5次输出的结果如下:

real 19.592s     18.517s      18.003s      20.470s     20.004s

usr 2.924s       2.964s       3.000s        2.812s       2.972s

sys 2.472s       2.360s       2.344s       2.652s       0.396s

2. 如果采用内存映射,将文件data.in映射到存储区,就避免的对文件的频繁读写操作,而全部转变为I/O存储读写。下面一个程序就是用mmap映射将文件data.in中每个数据加1存储到data.out中。

//mmapx2.c

#include

#include

#include

#include

#include

#define size 1024*1024*500

#define LEN 1024

int main()

{

int fdin,fdout;

struct stat statbuf;

void *src,*dst;

char *p;

int i,j;

fdin=open("data.in",O_RDONLY);

fdout=open("data.out",O_RDWR|O_CREAT|O_TRUNC);

if((src=mmap(0,size,PROT_READ,MAP_SHARED,fdin,0))==MAP_FAILED)

{

printf("src map error\n");

return -1;

}

lseek(fdout,size-1,SEEK_SET);

write(fdout,"\0",1);

//因为data.out是空文件,必须创建一个空洞让其大小成为size来进行下面的mmap

if((dst=mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,fdout,0))==MAP_FAILED)

{

printf("dest map error\n");

return -1;

}

memcpy(dst,src,size);

p=(char*)dst;

for(i=0;i

{

for(j=0;j

p[j]++;

p+=LEN;

}

printf("ok\n");

close(fdout);

return 0;

}

time测试的5次运行时间如下:

real 9.603s      8.977s      9.416s      9.587s      9.322s

usr 2.764s      2.748s      2.784s      2.840s      2.787s

sys 1.516s      1.384s      1.384s      1.224s      1.276s

结论:上面可以看到,对于频繁IO读写,采用mmap存储映射可以有效提高效率(20s到9s)

3.mmap内存映射还有一个好处,就是直接在一个文件内任意读写修改某个字节,就像操作存储区一样,比如下面一段程序是实现对data.in中每个字节数据加1的计算。

//mmapx3.c

#include

#include

#include

#include

#include

#define size 1024*1024*500

#define LEN 1024

int main()

{

int fd;

void *src;

char *p;

int i,j;

fd=open("data.in",O_RDWR);

if((src=mmap(0,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))==MAP_FAILED)

{

printf("src map error\n");

return -1;

}

p=(char*)src;

for(i=0;i

{

for(j=0;j

p[j]++;

p+=LEN;

}

printf("ok\n");

close(fd);

}

time测试的5次的运行时间如下:

real 2.820s     2.828s     2.856s     2.818s     2.889s

usr 2.624s     2.624s     2.676s     2.648s     2.584s

sys 0.196s     0.196s     0.176s     0.172s     0.288s

上面对一个大文件内的所有字节各自改变加1,并保存在原来的文件中,采用mmap存储映射的方法可以大大提高效率。对于频繁地随机改写某个文件内的某些部分字节内容的情况来说,这是一个有效的选择。

(feizf)

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值