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

简介:

本人在学习《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),这个过程是很慢的。 
目录
相关文章
|
3月前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
308 7
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
107 1
|
4月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
103 6
|
4月前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
103 31
|
4月前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
233 77
|
4月前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
192 62
|
1天前
|
消息中间件 Java 应用服务中间件
JVM实战—2.JVM内存设置与对象分配流转
本文详细介绍了JVM内存管理的相关知识,包括:JVM内存划分原理、对象分配与流转、线上系统JVM内存设置、JVM参数优化、问题汇总。
JVM实战—2.JVM内存设置与对象分配流转
|
3天前
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
|
4天前
|
存储 缓存 算法
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
JVM简介—1.Java内存区域
|
22天前
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
23 6