非托管资源
像系统对象(System objects)这样的资源自身都不是个问题 , 但本文仍涵盖了它们,因为像Windows这样的操作系统对可同时打开的 套接字、文件等的数量都有限制 。所以关注应用程序所使用系统对象的数量非常重要 。
在特定时间段内一个进程所能使用的User与GDI对象数目也是有配额的 。缺省值是10000个GDI对象和10000个User对象 。如果想知道本机的相关设置值,可以使用如下的注册表键:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows: GDIProcessHandleQuota 和 USERProcessHandleQuota.
猜到了什么?确实没有这么简单,还有一些你会很快达到的其它限制 。比如参照:我的一篇有关桌面堆的博客 所述 。
假设这些值是可以自定义的,你也许认为一个解决方案就是打破默认值的限制—调高这些配额 。但我认为这可不是个好主意,有如下原因:
1. 配额存在的原因:系统中不是只有你独自一个应用程序,所有运行在计算机中的其它进程与你的应用应该分享系统资源 。
2.如果你修改配额,使它不同于其它系统了 。你不得不确认所有你的应用程序需要运行的机器都完成了这样的修改,而且这样的修改从系统管理员的角度来说是否会有问题也需要确认 。
3.大部分都采用了默认配额值 。如果你发现配置值对你应用程序来说不够,那你可能确实有些清理工作要做了 。
如何检测泄露及找到泄露的资源
泄露带来的实际问题在MSDN上的一篇文章中有着很好的描述:
哪怕在小的泄露只要它反复出现也会拖垮系统 。
这与水的泄露异曲同工 。一滴水的落下不是什么大问题 。但是一滴一滴如此反复的泄露也会变为一个大问题 。
像我稍后解释的,一个无意义的对象可以在内存中维持一整图的重量级对象 。
仍然是同一篇文章,你会了解到:
通常三步根除泄露:
1.发现泄露
2.找到被泄露的资源
3.决定在源码中何时何处释放该资源
最直接“发现”泄露的方式是遭受泄露引发的问题
你或许没有见过内存不足 。“内存不足”提示信息极少出现 。因为操作系统运行中实际内存(RAM)不足时 , 它会使用硬盘空间来扩展内存 。(称为虚拟内存) 。
在你的图形应用程序中可能更多出现的是“句柄不足”的异常 。准确的异常不是System.ComponentModel.Win32Exception 就是 System.OutOfMemoryException 均包含如下信息:”创建窗体句柄错误” 。这两个异常多发于两个资源被同时使用的情况下 , 通常都因为该释放的对象没有被释放所致 。
另外一种你会经常碰到的情况是你的应用程序或是整个系统变更得越来越慢 。这种情况的发生是因为你的系统资源即将耗尽 。
我来做个生硬的推断:大多数应用程序的泄露在多数时间里都不是个问题,因为由泄露导致出现的问题只在你的应用程序集中使用很长时间的情况下才会出现 。
如果你怀疑有些对象在应该被释放后仍逗留在内存中,那需要做的第一件事就是找出这些对象都是什么 。
这看起来很明显,但是找起来却不是这样 。
建议通过内存工具找到非预期逗留在内存中的高级别对象或是根容器 。在项目x中,这些对象可能是类似LayoutView实例一样的对象们(我们使用了MVP(Model View Presentation )模式) 。在你的实际项目中,它可能依赖于你的根对象是什么 。
下一步就是找出它们该消失却还在的原因 。这才是调试器与工具能真正帮忙的 。它们可以显示出这些对象是如何链接在一起的 。通过查看那些指向“僵尸对象”(the zombie object)的引用你就可以找到引起问题的根本原因了 。
推荐阅读
- 节拍器下载,架子鼓节拍器下载
- flutter打包手机打不开,flutter打包ios并上架
- 电脑连接硬盘怎么连,电脑硬盘的连接
- mysql消耗过大怎么办 mysql耗cpu
- Python中个标点符号作用,python中标点符号的用法
- 直播加加为什么卡,直播加加直播有声音吗
- 游戏革命开发,革命时代游戏
- php原生语句查询数据库 php原生类
- mongodb索引慢,mongo索引调优