现象
用C#异步方式实现的网络底层协议,开发的服务器。上线运行一段时间后,发现一开始内存非常稳定,但是过了一定时间后,内存使用量会开始不停的上涨。直到内存耗尽。
排查
遇到这一问题可以明确的是内存发生了泄漏。由于.Net中,托管对象的内存是由垃圾回收机制负责回收的。所以存在内存增长的情况,往往不是因为没有释放。而是有几种原因
- 分配的内存,比垃圾回收的还要快
- 对象存在引用,没有办法被垃圾回收机制回收。
对于第一种情况,我仔细排查了代码中使用new分配内存的位置,往往这种情况,是因为在一个逻辑循环中不断分配内存,并且该循环占用了大量的CPU,导致其他线程(GC)没有空隙执行释放造成的。常见的是在一些线程函数中的,无限循环(业务逻辑的帧循环)中执行了new。
第二种情况则是我们以为我们分配的对象在生命周期结束后,不会再被其他对象引用,而应该被GC回收,但实际情况是因为某些原因(比如,函数返回,输出参数,将对应的引用返回到其生命周期外部),对象实际被其他对象使用了,导致GC不认为该对象是死对象,从而无法回收。这种情况比较多见,往往是编写代码的疏忽。
但针对以上两种情况进行排查后,我发现我们的代码都没有这种问题,因为对这个问题的排查陷入一个无解的情况。
由于在进程中,执行new的地方,除了业务逻辑,只剩下网络底层协议。因为把目光转向了网络底层实现。在我们的网络底层实现中,使用new的只有对网络消息的封包&#