就在前几天,我正在研究内存泄漏,该应用程序在两分钟内将应用程序从大约50MB膨胀到大约130MB。事实证明问题出在ConcurrentQueue类。在内部,该类存储数组的链接列表。当一个项目从ConcurrentQueue出队时,数组中的索引会被碰撞,但该项目仍保留在数组中(即它未设置为null)。在足够的入队/出队之后,整个阵列节点被丢弃,因此从技术上讲它不是 leak ,但是如果在ConcurrentQueue中放置大对象,这可能会很快失控。文件没有记录这种危险。
我想知道基类库中还有哪些潜在的内存缺陷?我知道Substring one(也就是说,如果你调用substring并保持结果,整个字符串仍将在内存中)。你遇到过的其他人吗?
答案 0 :(得分:11)
你是对的。该错误位于方法System.Collections.Concurrent.ConcurrentQueue<T>+Segment.TryRemove(out T, ref ConcurrentQueue<T>.Segment)
。
如果您在Reflector中查看此方法,您将看到以下行:
result = this.m_array[low];
之后应该有以下一行:
this.m_array[low] = default(T);
作为参考,您可以在方法System.Collections.Generic.Queue<T>.Dequeue()
中看到这是如何正确实现的。
答案 1 :(得分:0)
虽然不是直接内存泄漏或特定于.net / BCL,但是存在字符串连接(使用+ =运算符)问题。由于垃圾收集量很大,这在循环中非常耗费CPU。
答案 2 :(得分:-1)
ConcurrentQueue最多只能容纳31个出队对象。除非你正在处理非常大的对象图,否则这不应该是一个大问题。
无论如何,如果你没有空间来分配32个对象,那么使用ConcurrentQueue是没有意义的......