使用内存映射文件来提高你程序的性能

简介:

本人在学习《WINDOWS核心编程》的时候对JEFFREY大师提到的一个小程序写了两个版本来比较性能,该程序的原始需求是这样的:对一个大文件进行倒序,也就是将一个文件头变成尾,尾变成头。

  使用的方法有很多种,这里使用两个方法来比较,主要是突出使用内存映射文件好处;两种方法为:内存映射文件方法,I/O读写的缓存办法。

  第一种办法是创建内存映射文件对象,然后将该对象映射到进程的地址空间中,再读取文件内容,然后倒序,再写入文件。

  第二中方法是,将文件内容读入一个大的缓冲区,然后倒序,再写入文件,中间对原来的文件删除,然后重新写入。

  程序编写如下

  第一种方法, 内存映射文件方式
BOOL FileReverse(PCTSTR pszPathName)
{
HANDLE hFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL
,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("File could not be opened.");
return FALSE;
}


DWORD dwFileSize = GetFileSize(hFile,NULL);

HANDLE hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,
dwFileSize+sizeof(char),NULL);

if(hFileMap == NULL){
CloseHandle(hFile);
return FALSE;
}


PVOID pvFile = MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,0);

if(pvFile == NULL){
CloseHandle(hFileMap);
CloseHandle(hFile);
return FALSE;
}


PSTR pchAnsi = (PSTR)pvFile;
pchAnsi[dwFileSize/sizeof(char)]=0;
_strrev(pchAnsi);

pchAnsi = strchr(pchAnsi,'\n');
while(pchAnsi != NULL){
*pchAnsi++ ='\r';
*pchAnsi++ ='\n';
pchAnsi = strchr(pchAnsi,'\n');
}


UnmapViewOfFile(pvFile);
CloseHandle(hFileMap);

SetFilePointer(hFile,dwFileSize,NULL,FILE_BEGIN);
SetEndOfFile(hFile);//实际上不需要写入了。
CloseHandle(hFile);

return TRUE;
}


第二中方法, 使用缓存的方式
BOOL FileReverseNoMap(PCTSTR pszPathName)
{
HANDLE hFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL
,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
printf("File could not be opened.");
return FALSE;
}


DWORD dwFileSize = GetFileSize(hFile,NULL);
//CloseHandle(hFile);
char *readBuf = new char[dwFileSize+1];
DWORD nRead = 0,nRet =0;
while(nRead<dwFileSize){
if(ReadFile(hFile,readBuf+nRead,dwFileSize-nRead,&nRet,NULL) ==TRUE)
{
nRead+= nRet;
}

else
{
printf("Can read the file!");
CloseHandle(hFile);
}

}


PSTR pchAnsi = (PSTR)readBuf;
pchAnsi[dwFileSize/sizeof(char)]=0;
_strrev(pchAnsi);

pchAnsi = strchr(pchAnsi,'\n');
while(pchAnsi != NULL){
*pchAnsi++ ='\r';
*pchAnsi++ ='\n';
pchAnsi = strchr(pchAnsi,'\n');
}

CloseHandle(hFile);
DeleteFile(pszPathName);

HANDLE hWriteFile = CreateFile(pszPathName,GENERIC_WRITE|GENERIC_READ,0,NULL
,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
WriteFile(hWriteFile,readBuf,dwFileSize,&nRet,NULL);
CloseHandle(hWriteFile);

delete readBuf;

return TRUE;
}

 我运行了几次,比较结果如下:
文件大小(byte) 1方法时间(ms) 2方法时间(ms)
25416 0 0
101664 0 0
406656 0 10
1219968 10 30
3202416 21 100
9607248 80 551
67250736 581 5568

  本人测试机器的CPU是迅池1.5的笔记本,内存为712MB

  通过上面的测试我们可以看到使用内存映射文件的好处,在文件内存越大这种优势就体现的越明显,其中主要的原因是:

  内存映射文件直接将文件的地址映射到进程的地址空间中,那么操作文件就相当于在内存中操作一样,省去了读和写I/O的时间;第二种方式是必须这么做(READFILE,WRITEFILE),这个过程是很慢的。 
目录
相关文章
|
2月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
195 77
|
2月前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
140 62
|
2月前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
79 31
|
1月前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
126 7
|
2月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
57 6
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
71 1
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
421 1
|
1月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
2月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80
|
2月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
27 3