gpt4 book ai didi

C# ConcurrentBag迭代时的内存消耗

转载 作者:太空狗 更新时间:2023-10-30 00:18:43 26 4
gpt4 key购买 nike

如果我先贴出代码会更容易:

static void Main(string[] args)
{
List<double> testLst = new List<double>();
for (int i = 0; i < 20000000; i++) { testLst.Add(i); }

我用 20,000,000 个元素填充了一个列表。我在任务管理器中看到该进程正在使用 ~300MB。如果我使用 foreach 循环遍历列表:

    foreach (var a in testLst.Take(10)) 
{
Console.WriteLine(a);
}
}

内存使用量没有增加(我在 Console.WriteLine 上放置了一个断点,正如我所说,我正在使用任务管理器对其进行测量)。现在,如果我用 ConcurrentBag 替换 List:

static void Main(string[] args)
{
ConcurrentBag<double> testCB = new ConcurrentBag<double>();
for (int i = 0; i < 20000000; i++) { testCB.Add(i); }

foreach (var a in testCB.Take(10))
{
Console.WriteLine(a);
}
}

foreach 循环之前的内存使用量为 450~500MB。问题是:为什么 if 在 foreach 循环内部使用会跳到 ~900MB?

我预计 ConcurrentBag 会比 List 消耗更多内存,但我不明白为什么迭代要使用这么多内存。

(我在类似但不同的场景中使用 ConcurrentBag,我知道在这种情况下使用它没有意义)

最佳答案

来自 ConcurrentBag.GetEnumerator docs (强调我的):

The enumeration represents a moment-in-time snapshot of the contents of the bag. It does not reflect any updates to the collection after GetEnumerator was called. The enumerator is safe to use concurrently with reads from and writes to the bag.

查看 source ,你可以看到它创建了包的副本:

public IEnumerator<T> GetEnumerator()
{
// Short path if the bag is empty
if (m_headList == null)
return new List<T>().GetEnumerator(); // empty list

bool lockTaken = false;
try
{
FreezeBag(ref lockTaken);
return ToList().GetEnumerator();
}
finally
{
UnfreezeBag(lockTaken);
}
}

顾名思义,ToList()返回 List<T> (不是扩展方法,是私有(private)成员函数)。

作为旁注,return new List<T>().GetEnumerator();线条不漂亮......可以写成return Enumerable.Empty<T>().GetEnumerator();相反。

关于C# ConcurrentBag迭代时的内存消耗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31662544/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com