简单描述下俺要废话的背景吧,这几天都在排查一个bug:silverlight客户端应用中的某个控件,会因为多次操作而导致浏览器内存飙升,至于飙升的速度嘛,差不多操作半个小时后,浏览器估计就累死了……
接到这个棘手的活儿后,先大概捋了一下自己的思路:
1. 复现问题:并掌握问题复现的“规律”。
2. 熟悉问题控件的生命周期:一方面是控件的需求功能,一方面是控件的代码实现。
3. 用阶段排除法定位可疑代码段:主要是通过调试、观察,逐渐缩小问题包围圈。
4. 仔细研究可疑代码段:尽量能够连其上下文都要进行了解,以避免引入新的问题。
5. 思考具体的解决方案,并进行可行性尝试。
6. 修改代码,并更新。
乍看上去,还是很“美好”的,真正开始搞起来以后,才发现其实还是很棘手的,具体表现:问题很容易复现,控件生命周期在同事的热心帮助下也能基本搞懂,用排除法定位到了“问题代码段”,看似顺风顺水的,还不赖哈,下面就出事儿了,需要对代码段进行细致研究,这一研究不要紧,一头扎进去就不容易爬出来了……
发现问题是因为载入的silverlight控件的内容较大,所以导致载入的对象比较大,此外,最主要的还是因为每次操作都会导致一个新的对象生成,于是很直接地就想到了,时不时有一些资源无法被GC放掉,于是导致了内存溢出呢?既然选择了这条路,那么就要一路走到底了,首先先把该控件涉及到的内容进行分类,然后逐一地进行删减以排查最终的“内存杀手”到底是谁……不过运气不好,发现通过silverlight载入控件的时候可能会导致一些模板类的资源无法得到释放,但是经过单独的demo测试又没有重现问题,继续通过windbg来查看IE进程的内存使用情况,发现其中一部分日志功能代码导致了一部分的内存溢出,大概占整体GC内存占用量的16%左右,算是一个小小的成果吧;但貌似继续追查下去也只能到这儿了,因为我们发现GC占用的内存总量才占到IE进程的10%左右,有90%的内存怀疑是被一些非托管的资源占用了,但说到我们到底有啥办法改善上面,貌似是无能为力了
但是问题还要解决的,于是再次重新Review全部功能代码,发现在第一开始确定解决问题思路的时候,貌似自己遗留了关键的一点:“每次创建新对象……”,好吧,这是自己马虎了,总想着从纵向地根除问题,但是没有想到从横向去解决问题,如果我能保证所有对该控件公共属性面板的引用只有一个的话,是不是问题就解决了呢?答案是:Yes!
虽然不可思议,但问题终于是解决了,虽然还留下一点儿小小的遗憾……
回过头来看看这次的经历,还是有所收获的:
1. 首先,在排查问题的时候,做做小计划还是很有必要的;
2. 再者,一旦定位问题的大致原因,不要急着按照自己想到的第一种方法深入,不妨再想想有没有其他的办法来解决问题;
3. 不管你信不信,有的时候,我们可能找不到最终的原因,但我们必须要解决问题!这一点可能存在争议,但我觉得在面对上线在即的产品研发的最后阶段,是可以适当采取一些“妥协”的方案的,但这并不意味因为困难,这问题就不解决了,我们完全可以放到后面的时间再去深入地解决。
以上就是自己在这次经历后的一点小小体会,分享给大家,希望能对大家有所帮助!~