为什么我们要调用队列的TrimToSize方法



队列的容量是队列可以容纳的元素数。当元素被添加到队列中时,容量会根据需要通过重新分配自动增加。可以通过调用TrimToSize来减少容量。

这是在MSDN队列文档中编写的

现在的问题是,在一个队列中,如果我们添加了大约2万个项目,那么该队列将逐个取消排队,直到队列为空。如果我们不调用TrimToSize函数,那么队列大小将保持为20000,但数据由垃圾收集器删除,因此从技术上讲没有内存泄漏,如果我们检查计数或序列化队列,则大小为空队列那么我们为什么要调用TrimToSize函数呢

您将队列中对象的GC与队列本身的内存"槽"混淆了。

队列将分配空间来存储所有的20K引用。。。。这些插槽将是空的,因此不会指向占用更多内存的对象。但这些"槽"将一直存在,等待分配给它们的引用。

假设队列将项目存储在内部数组中,当容量增加时,将分配一个新数组,并将项目从旧的较小大小的数组移动到此新数组。

假设初始容量为16,则在存储器中分配长度为16的阵列。现在,您的数组已经增长到20000,这可能是由于算法中的峰值,并且一旦处理完所有作业,队列只包含1个项目。这次您使用的是长度为20000的数组。在这种情况下,您的队列占用了太多的内存。

队列将主要用于长时间运行的任务管理算法,其中内存的使用将非常动态。减少容量将有助于获得更好的性能,因为如果您有许多实例,并且每个实例都会增长,那么您将有大部分内存未使用。

在这个场景中,我更喜欢使用链表。

考虑两组对象:

queue       other things
+------+
| slot | -> item
| slot | -> item
| slot | -> item
:      :
| slot | -> item
+------+

虽然项目本身在不再使用时可能会被垃圾收集,但这不会影响单个对象,即仍在使用的队列。

然而,当你的负载很高时,它可能已经扩展到了无数个插槽,在被告知其他情况之前,它会保持这个大小。

通过在队列上调用TrimToSize,可以减少正在使用的插槽的数量,从而可能将内存释放回可用池以用于其他目的。

即使不添加大量元素,队列也会变得相当大,因为您可以为其配置高乘数(添加到完整队列时其容量乘以的值(。

这只是很好的内存管理,通常用于您知道队列不会再次增加大小的队列。

一个典型的例子是从文件中读取配置项。一旦你读过它们,它们的大小就不太可能再次增加(直到你重读文件,这通常是不常见的(。

如果您的队列可能会频繁地上下变化,那么最好使用TrimToSize而不是

容量不会逐个增加。如果我没记错的话,每当大小达到阈值时,容量就会翻倍。TrimToSize将容量设置为完全相同的大小。

通常您不需要调用该方法。但是,在某些情况下,您可能希望封送或序列化。

安德鲁所说的也是非常真实的。

Queue使用object[]作为hold元素,因此即使将所有元素出列,您也会在内存中拥有长度为20000的数组

最新更新