c – 为什么用mmap顺序读取一个大文件,而madvise顺序比fgets慢?
概观
我有一个由IO显着限制的程序,我正试图加快它. 一些演示代码 我已经将演示文稿简化为必需品,测试了一个大约350万行的800mb文件: 随着fgets: char buf[4096]; FILE * fp = fopen(argv[1],"r"); while(fgets(buf,4096,fp) != 0) { // do stuff } fclose(fp); return 0; 运行时800mb文件: [juhani@xtest tests]$time ./readfile /r/40/13479/14960 real 0m25.614s user 0m0.192s sys 0m0.124s mmap版本: struct stat finfo; int fh,len; char * mem; char * row,*end; if(stat(argv[1],&finfo) == -1) return 0; if((fh = open(argv[1],O_RDONLY)) == -1) return 0; mem = (char*)mmap(NULL,finfo.st_size,PROT_READ,MAP_SHARED,fh,0); if(mem == (char*)-1) return 0; madvise(mem,POSIX_MADV_SEQUENTIAL); row = mem; while((end = strchr(row,'n')) != 0) { // do stuff row = end + 1; } munmap(mem,finfo.st_size); close(fh); 运行时变化很大,但从不比fgets快: [juhani@xtest tests]$time ./readfile_map /r/40/13479/14960 real 0m28.891s user 0m0.252s sys 0m0.732s [juhani@xtest tests]$time ./readfile_map /r/40/13479/14960 real 0m42.605s user 0m0.144s sys 0m0.472s 其他说明 >观看流程在顶部运行,memmapped版本在此过程中产生了几千个页面错误. 问题 >为什么会这样?是不是因为fopen / fgets实现的缓冲文件访问比使用madvise POSIX_MADV_SEQUENTIAL进行mmap的积极预取更好? 解决方法
POSIX_MADV_SEQUENTIAL只是对系统的提示,可能会被特定的POSIX实现完全忽略.
两种解决方案之间的区别在于mmap要求将文件映射到虚拟地址空间,而fgets在内核空间中完全完成IO,只是将页面复制到不会更改的缓冲区中. 这也有更多的重叠可能性,因为IO是由某个内核线程完成的. 您可以通过让一个(或多个)独立线程读取每个页面的第一个字节来提高mmap实现的感知性能.然后,这个(或这些)线程将具有所有页面错误以及应用程序线程将在已经加载的特定页面上的时间. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |