【发布时间】:2019-06-03 13:31:05
【问题描述】:
我使用ConcurrentDictionary<String, String> 来存储大量数据(4 500 000 个条目),并且我不想使用额外的内存,所以我一开始就固定了容量。但是字典在达到指定容量之前会自动增长。
我写了一小部分代码来展示只有 500 个项目的问题,我对私有存储桶数组进行了反思,因为我没有找到提供真实容量的公共属性:
using System;
using System.Collections.Concurrent;
using System.Reflection;
namespace MemoryUsage
{
class Program
{
static void Main(string[] args)
{
CapacityTest();
}
private static void CapacityTest()
{
int capacity = 500;
ConcurrentDictionary<String, String> dict = new ConcurrentDictionary<string, string>(Environment.ProcessorCount, capacity);
Console.WriteLine("{0} buckets", GetBucketCount(dict));
for (int index = 0; index < capacity; index++)
dict.AddOrUpdate(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), (key, value) => value);
Console.WriteLine("{0} buckets", GetBucketCount(dict));
Console.ReadLine();
}
private static int GetBucketCount(ConcurrentDictionary<string, string> dict)
{
object tables = dict.GetType().GetField("m_tables", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(dict); // "_tables" with .NET Core, "m_tables" with .NET Framework
object buckets = tables.GetType().GetField("m_buckets", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tables); // "_buckets" with .NET Core, "m_buckets" with .NET Framework
return ((Array)buckets).Length;
}
}
}
显示:
500 buckets at the beginning
1003 buckets at the end
我期待500 buckets at the end。由于我知道开头的项目数,您知道避免分配额外内存的方法吗?
【问题讨论】:
-
我不知道这一点。我认为您可以使用缓存类。 docs.microsoft.com/en-us/dotnet/framework/performance/…
-
这似乎与值的分布有关。我用一组处理器计数 = 8 的整数 (0-7) 尝试了你的代码。然后只有 8 个桶。
-
ConcurrentDictionary必须允许一些松弛以允许多线程的无锁操作。如果您使用1或2而不是Environment.ProcessorCount,您将获得最少的桶(至少在我的系统上)。显然,这并不完全是您可以指望的,因为它还取决于您的价值分配。 -
你说得对@JeroenMostert,用 1 代替
Environment.ProcessorCount,容量得到尊重。但我想它会降低多线程环境下的性能,我必须检查一下。
标签: c#