性能工具设计简介

作者: admin 分类: 开发问题 发布时间: 2015-02-11 14:21 ė1,958 浏览数 6没有评论
文章转自王牌软件
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)

客户端的性能是用户体验的一个非常重要的方面。在需求设计时要考虑到可能的性能问题;在不断的迭代开发新功能的同时要保持性能的稳定;在运营过程中要能追踪并解决历史遗留的性能问题。工欲善其事,必先利其器。虽然有不少现成工具可以使用,但自己设计性能工具更灵活,更有针对性。性能工具的主要功能是监控目标程序获取相关数据,以及一定的数据组织和分析能力,帮助我们找出性能瓶颈定位问题。我们通过把数据以时间轴的方试记录下来,然后对数据进行分析定位到发生问题的时间点并找出解决方法。

需要哪些数据

常见的性能问题主要是:界面卡、反应慢、CPU高、内存大等几个方面。我们针对这些来考虑需要的数据以及如何来记录这些数据(针对windows客户端)。

  1. 界面卡、反应慢 

界面卡、反应慢就是程序的响应速度,主要有:界面对鼠标键盘输入的响应速度;一些比较耗时的系统API速度,比如读写文件等;还有一些则是针对目标程序的一些关键路径执行速度。

界面响应速度,这里我们可以采用每次消息循环的执行的时间点以及时间消耗来判断。对于大多数windows程序来说hook GetMessage并记录下来每次调用GetMessage的时间就可以了。但也有些客户端自己实现的消息循环,这里我们就需要hook对应的函数(比如PeekMessage)或是在消息循环里加上log。另外我们也可以向目标程序发送WM_NULL消息跟据其响应时间来判断响应速度。在这里,上述两种方法我们都推荐50ms做为一个判断标准。

系统API执行速度,用hook的方法记录调用的线程ID、时间点、消耗时间以及一些必要的参数。hook一些需要关注的API即可,比如CreateFile ReadFile WriteFile BitBlt StrenchBlt等等。

对于一些关键路径,我们同样需要记录下来执行时的线程ID、时间点和时间消耗。这一点针对性比较强,直接在目标程序加入log就可以了。当然同样可以用hook的方法,但不推荐。Hook的实现比较复杂,需要实现一个跳板函数,在跳板函数中相关信息。更适应于记录一些调用次数多的系统级API。而一些关键路径往往与目标程序逻辑密切相关,整个过程只有几次调用,甚至可能只有一次或完全不调用。这样就完全没有必要用hook的方法。

系统API和关键路径(函数)的耗时,推荐用记录开始时间和结束时间两个数据。这样在有嵌套的情况下,比记录消耗时长,更直观。

hook?这里推荐用微软的detours库。detours2.1版本之前是开源的。Detours的基本原理是这样的:1. 把目标函数的前几行指令拷贝到一个地方,然后在原来的位置替换成一条跳转指令。2. 通过跳转指令跳转到自己实现的跳板函数,在跳板函数就可加入自己的代码了。如下:

image001

image002 

  1. 高、内存大

针对CPU高、内存大,我们简单以时间轴的方式按固定的时间间隔记录下来目标进程的CPU和内存的消耗就可以了。在CPU占用方面我们也可以更进一步记录下每个线程的CPU消耗。

  1. 有了上面的数据就够了吗?

不够。比如,当我们收集到一组数据。分析后得出,目标进程在启动后35秒-40秒的这段时间对WM_NULL消息无响应(界面卡住)。然后呢?然后我们仍然没有办法知道为什么会卡,以及卡在哪里。所以我们还需要目标的调用堆栈。同样以时间轴的方式按固定的时间间隔记录下堆栈信息。这样当我们发现问题时,便能得到目标的一个执行堆栈。接下来通过review代码解决问题。

至于获取调用堆栈。微软提供的 StackWalk64 就可以了,请MSDN。当然如果你喜欢自己通过堆来还原调用堆栈,那么就可以通过NtQueryInformationThread 取得线程信息后,根据ebp esp回溯也可以。

  1. 还需要哪些数据?

任何你关注的数据都可以记录下来。假如你关注IO对性能的影响,那么就记录下IO量和页面错误的数据;你怀疑是不是有其它模块的注入影响了你的程序,那么你也可以记录下来目标进程的模块信息……

组织分析数据

把数据初步整理,以图形的方式直观的表现出来。下面举几个例子。

用树表示关键函数的执行所花的时间。

image003

用线形图来表示CPU占用

image004

纵向表示占胜率,横向表示时间。用颜色来区分用户态CPU和内核态CPU。类似这样的图还可以用来表示无响应时间,内存占用等。

另外我们也可以自动分析堆栈数据,找出一段时间内连续出现在堆栈中的函数,在线形图上醒目标出。因为这种情况很有可能是卡住或阻塞了。如下图红线所占有的时间段内表示主线程堆栈中都有USER32.dll 77D18816调用,再配合PDB就知道调用的是哪个函数了。这样可以方便的找出性能瓶颈。

image005

还有其它各种表现形式,我们完全可以跟据自己的需要来实现。

性能工具本身的影响

上面提到的获取数据的方法,本身就会有性能的开销。比如增加log。注入后Hook相关函数等等。这些负面影响不可避免的,我们尽量将其影响减少。比如在记录内存开销时减掉log所占用的内存。Log写入文件也会带来IO开销,我们就采用先将log写入内存,当数据采集停止后一次性写入文件等。

总结

总之,开发自己的性能工具,首先要明确自己关注哪些性能点,然后在此基础上确定所需要的数据。最后确定下来性能工具的需要哪些功能,接着一步一步实现它就好了。最后别忘了跟据自己的需要持续改进。



只回答业务咨询点击这里给我发消息 点击这里给我发消息

学习日记,兼职软件设计,软件修改,毕业设计。

本文出自 学习日记,转载时请注明出处及相应链接。

本文永久链接: https://www.softwareace.cn/?p=1204

0

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">


Ɣ回顶部

无觅相关文章插件,快速提升流量