我正在使用List<等标准集合。 T>,HashSet< T>和词典< TKey,TValue>存储100万件物品,高达百万件。特定于用例的是,在开始时设置为巨大的项目变得非常慢并且在内存中保留很长时间。所以我面临的问题(尽管LOH分配/碎片是另一个问题)是这些集合消耗了大量内存,因为它们的内部逻辑在每次用完可用空间时将分配的内存加倍(实际上它是双倍和看起来最近的素数)。在我的情况下,添加很少,保留所有额外的内存是浪费。
以下是我如何处理List的简化版本:
public static void Add_GrowSlow<T>([NotNull] this List<T> list, T item, int growStep)
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (growStep <= 0)
throw new ArgumentOutOfRangeException(nameof(growStep));
var count = list.Count;
if (list.Capacity == count)
{
if (count > 10000)
{
list.Capacity = count + growStep;
}
}
list.Add(item);
}
但我不知道如何在没有反射的情况下处理HashSet / Dictionary。您能否建议任何方式或收集以避免此类问题?我查看了PowerCollections,但没有找到解决此问题的方法。
更新:我想澄清一下我想得到什么样的答案:nuget包的名称或链接到带有源代码的文章,其中集合可以控制它们的增长方式,实施。因为我的问题的明显解决方案是从BCL复制源代码并使那些现有方法受到虚拟保护:
class HashSet<T>
{
// ...
protected virtual void IncreaseCapacity() {...}
}
class Dictionary<TKey, TValue>
{
// ...
protected virtual void Resize() {...}
}
我不知道为什么他们从一开始就没有在BCL这样做。与重新分配和复制数据相比,虚拟调用的成本无关紧要。可能是我应该创建拉取请求?... :)