前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >win32应用程序性能测试-内存篇

win32应用程序性能测试-内存篇

作者头像
腾讯移动品质中心TMQ
发布2018-02-08 11:08:59
1.4K0
发布2018-02-08 11:08:59
举报

本文主要讲述windows平台下应用程序性能测试的内存相关的知识,通过本文了解内存基本原理和分析内存占用问题。

一、内存是什么?

1内存分为物理内存和虚拟内存

物理内存指通过物理内存条而获得的内存空间,虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间)。

2两者都有系统约定的最大值

进程占用的内存一般是指物理内存,其中操作系统为每个进程的工作集定义了一个最小和最大工作集。每个进程的 工作集有最小工作集(20-50M)最大是45-345M

虚拟内存:每个32位的进程操作系统为其分配最大4G的线性虚拟地址空间,地址是从0X00000000~0XFFFFFFFF 其中低的2G留给进程,高的2G留给系统。

3查看物理内存和虚拟内存

1电脑配置

例如我的电脑配置是 :如下,安装的内存是16G。查看资源监视器里显示,所以平时所说的内存占用是指物理内存。

2内存在资源管理器概念

例如这里进程: 物理内存(工作集)=可共享+专用

工作集:是私人工作集中的内存数量与进程正在使用且可以由其他进程共享的内存数量的总和。 专用工作集:- 是工作集的一个子集,专用工作集专门描述了某个进程正在使用的且无法与其他进程共享的内存数量。 提交大小:是为某进程使用而保留的虚拟内存的数量。

3虚拟内存查看

虚拟内存,用VMMAP工具查看。如下图

具体含义可以去网上搜索。其中虚拟内存有三种状态:

1)自由(free)是指内存还未使用。

2)当申请内存使用VirtualAlloc传入MEM_RESERVE执行预留(reserved)操作。

3)当真正访问内存的数据才执行提交(committed),传入MEM_COMMINT参数。

二、系统如何管理内存

1系统使用PFN数据库

系统使用PFN(Page Frame Number)数据库来存储物理内存。分几类page list来存储,如下面的图

  • Freelist :可用来分配,但是含有脏数据
  • modified:以前属于某个进程,但是需要写入到后备存储,为备后面恢复
  • standby :跟进程关联,但是不计算在工作集里
  • zero:置0后用来分配

可缓存内存是指在smodified和standby上的,可用的内存是指在zero \free\standby lists,如果这个值小于800M的话。windows就会消减工作集,会导致整体性能变差。

2操作过程

1)windows启动时,所有的内存全部是在 free page list.当进程请求内存时,(我理解为发生一次错误,从zero page file)。进程退出,则会将内存还到 free page list。

2)操作系统有两个线程会执行一些操作,一个是zero page thread,当要将free page移动到zeroed page时 进行置0 free page

3)第二个是 modified page writer,将modified page list移动到 standby page list时,进行第一次写出任何数据

页错误

1什么是页错误

访问数据时,进行虚拟地址映射到物理地址过程中,硬件检查页表时,发现所访问的页面不在内存,就产生异常--缺页异常,这个缺页异常就叫做页错误。

操作系统会执行缺页异常处理程序:获得磁盘的地址、启动磁盘、将该页调入内存。

如下图,是<<微软核心编程>>里例子,当访问的数据不在内存中就会发生一次fault,其中当访问page不在modified和standy里,则会发生HardPageFault。HardPageFault需要去系统的pagefile.sys里查找,这个查找过程会产生大量的IO操作,影响性能。

2 页错误的类型

Transition:是指访问的page是指在 modify或者stadby page list上

DemandZero:进程请求内存是,调用是zero page list

HardPageFault:访问的page不在工作集里,需要去磁盘pagefile去查找

copy on write:写入copy-on-write page。例如你要hook一个kernel上的函数,就是操作kernel上的page,需要先拷贝一份,这样不会影响其它进程使用kernel上的函数,这个操作就会发生一次copy on write错误

内存的分配API

1)利用 HeapAlloc 方法或 C/C++ 运行时中的 malloc 或 new 来进行堆内存分配。

2)利用 VirtualAlloc 方法从系统中直接分配内存。VirtualAlloc是Windows提供的API,通常用来分配大块的内存

3)由内核通过 CreateFile, CreateEvent, or CreateThread 等 Kernel32 APIs ,来代表应用程序进行处理

4)利用 User32 和 Gdi32 APIs 来处理 GDI 和 USER 。(默认情况下,每一个线程都有 10,000 处理( 10,000 handles )配额)

三、如何优化内存占用高的问题

1刷内存

刷内存SetProcessWorkingSetSize

1原理

函数用来设置应用程序最小和最大的运行空间,只会保留需要的内存,例如我们的部分exe里是有刷内存,这里设置的最小8M,最大14M

2缺点

刷内存只是将可能暂时不需要工作集swap出去,如果业务又再需要,需从虚拟内存的pagefile里调用过来,这个过程反而降低系统性能,所以不推荐使用

2减少页错误

这里推荐的操作是预处理,减少随机IO等。

3查找占用不合理和分配不合理的地方

1例子:某个dll 申请内存不合理

分析过程

1)抓取对应exe启动过程中VirtualAlloc。

2)查看启动过程中过程中VirtualAlloc分配的类型是AIFO【AIFO是指在此阶段分配但未释放,这种就是可疑的分配点】。发现其中有一段每次分配495K

3)查看对应的分配堆栈如下,发现是调用CreateToolhelp32Snapshot方法,引起这次分配。查看系统API。CreateToolhelp32Snapshot可以通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照。

4)查看源码,发现这里是每隔3S,去查询系统所有进程的一个快照,所以每次大小都有接近500K。而且场景的触发频率非常高,每隔1S检测一次,后面跟开发核实,这里的逻辑不应如此设计

5)通过这个问题,我们可以去系统检索一个分配内存大的函数,例如CreateToolhelp32Snapshot,是不是所有触发逻辑合理,轮询调用是非常不合理,应该要规避,而且这个代码是常驻的。这个留在后面形成相应的规则

2

例子:是内存泄露还是?

例子:某个版本的资源挂机突然VM增加,是内存泄露还是?

1)现象:如下图一个内部版本,在某个长时间挂机,突然出现在1个小时和4个小时后,内存增长10M的样子。时间跨度长,如何获取增长时的内存分配堆栈?

方法一、在内存增长时,trace。缺点:无法准确捕获这个时刻

方法二、看图,应该在1个半小时能出现,一直trace这个过程的VirtualAlloc和heapAlloc。因xperf开启heapalloc 消耗太大,只能针对指定进程进行trace

2)复现过程:

  • 安装同样的版本,发现本地也会出现VM从32M最后涨到50M的情况。
  • 设计trace的日志

Xperf -on PROC_THREAD+LOADER+CSWITCH+DISPATCHER+VIRT_ALLOC -stackwalkCSwitch+ReadyThread

xperf -start HeapSession -heap -Pids 18908 -BufferSize 1024 -MinBuffers 128 -MaxBuffers 128 -stackwalkHeapAlloc+HeapRealloc

注:第二条是开启heapsession来trace 指定进程的heapalloc。整个过程etl太大,全部需要输出到文件模式

  • 分析trace过程的分配。

如下图,查看到这个过程有几个分配大的点。其中有一个1M到4M,增长3M的情况和对应的堆栈。

其中0xfd10000这个对象分配3.176M,这个堆栈全部都是系统的API

  • 对应CPU调度图来查看是什么原因导致这个分配,这里表现是一个TPKTT.dll
  • 查看当时的内存dump,查看0xfd10000对象,调用的堆栈是文件监控里
  • 结合上面,怀疑是文件监控导致的,但是跟开发确认文件监控很久未变更,而且文件监控是底层逻辑,所有业务会触及。另一方面,查看TPKTT.dll相关的信息,他们的里面的逻辑没有泄露点
  • 是不是挂机的现象和我这不一样,同样在挂机的机器上抓trace日志,最后问题点是一样的
  • 再次分析内存分配的堆栈,向前查看,发现调用文件监控逻辑前有一个Loadlibrary的操作,而且TPKTT.dll的大小正好也是3M多
  • 开发再次排查他们的逻辑,原来在静默1个小时后,会触发引擎的TPK的逻辑,这里,概会增加10到13M的样子,所以RTP VM 增加属于业务的需要,引擎库加载需要内存。这个逻辑触发在70分钟到90分钟之间。因为我们的挂机以前只挂1个小时,这次是因为验证其它问题,所以挂机时间长出现这个问题。经过2天的定位,终于确认这次增长。

四、结尾

性能里调优内存涉及的点比较多,上面几个例子只是部分。建议平时先建设基础基准数据,有业务增加及时定位。

附我们内存优化的一些方向:

参考文章:

https://blogs.msdn.microsoft.com/tims/2010/10/29/pdc10-mysteries-of-windows-memory-management-revealed-part-two/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-01-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯移动品质中心TMQ 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、内存是什么?
  • 二、系统如何管理内存
  • 三、如何优化内存占用高的问题
  • 四、结尾
  • 参考文章:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档