由于工作中频繁涉及文件IO,借周五下午的一点空隙,研究了一下标准IO库的IO效率和文件映射机制的IO效率。我用一个2G的数据文件作为测试对象,该数据文件中一共有6213834条记录,每一行为一条记录。file_fgets函数用fgets的方法来按行读取数据,file_mmap函数先使用mmap机制来把这个大文件映射到程序内存,然后再按行解析数据记录。
源代码如下:
#include <cstdio> #include <cstdlib> #include <cstring> #include <sys/stat.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> using namespace std; //用fgets的方式读取文件 int file_fgets(const char *pFileName) { FILE *fp=fopen(pFileName,"r"); char strLine[600]; size_t nLineAmount=0; while(!feof(fp)) { memset(strLine,0,sizeof(strLine)); fgets(strLine, sizeof(strLine), fp); nLineAmount++; } fprintf(stderr,"一共读取了%u条记录./n",nLineAmount); fclose(fp); return 0; } int file_mmap(const char *pFileName) { char *pBuffer=NULL; char *pStart=NULL,*pEnd=NULL; int fd=open(pFileName,O_RDONLY); size_t nFileSize=0; size_t nOffset=0; size_t nLineAmount=0; struct stat fileState; fstat(fd,&fileState); nFileSize=fileState.st_size; pBuffer=(char *)mmap(NULL,nFileSize,PROT_READ,MAP_SHARED,fd,0); pEnd=pStart=pBuffer; while(pEnd!=NULL) { pEnd=strchr(pStart,'/n'); pStart=pEnd+1; nLineAmount++; } fprintf(stderr,"一共读取了%u条记录./n",nLineAmount); munmap(pBuffer,nFileSize); close(fd); return 0; } int main() { char strTestFile[255]="test_2G.txt";//测试文件名,大小2G左右,一共有6213834条数据 struct timeval tpStart; struct timeval tpEnd; gettimeofday(&tpStart, NULL); file_fgets(strTestFile); gettimeofday(&tpEnd, NULL); printf("用fgets的方式消耗时间:%ld/n",tpEnd.tv_sec-tpStart.tv_sec); memset(&tpStart,0,sizeof(tpStart)); memset(&tpEnd,0,sizeof(tpEnd)); gettimeofday(&tpStart, NULL); file_mmap(strTestFile); gettimeofday(&tpEnd, NULL); printf("用mmap的方式消耗时间:%ld/n",tpEnd.tv_sec-tpStart.tv_sec); return EXIT_SUCCESS; }
测试结果:用mmap的机制效率比fgets会高一点,原因在于mmap少了内核空间到用户空间的拷贝操作