【发布时间】:2018-04-11 01:46:05
【问题描述】:
我正在使用包含约 100 万个键的可靠字典来评估 Service Fabric 的性能。我得到了相当令人失望的结果,所以我想检查一下我的代码或我的期望是否错误。
我有一个用初始化的字典
dict = await _stateManager.GetOrAddAsync<IReliableDictionary2<string, string>>("test_"+id);
id 对于每次测试运行都是唯一的。
我用一个字符串列表填充它,比如 "1-1-1-1-1-1-1-1-1", "1-1-1-1-1-1-1-1-2", “1-1-1-1-1-1-1-1-3”.... 多达 576,000 个项目。字典中的值没有使用,我目前只是使用“1”。
将所有项目添加到字典大约需要 3 分钟。我必须一次将事务拆分为100,000,否则它似乎永远挂起(在需要CommitAsync()之前,事务中的操作数是否有限制?)
//take100_000 is the next 100_000 in the original list of 576,000
using (var tx = _stateManager.CreateTransaction())
{
foreach (var tick in take100_000) {
await dict.AddAsync(tx, tick, "1");
}
await tx.CommitAsync();
}
之后,我需要遍历字典来访问每一项:
using (var tx = _stateManager.CreateTransaction())
{
var enumerator = (await dict.CreateEnumerableAsync(tx)).GetAsyncEnumerator();
try
{
while (await enumerator.MoveNextAsync(ct))
{
var tick = enumerator.Current.Key;
//do something with tick
}
}
catch (Exception ex)
{
throw ex;
}
}
这需要 16 秒。
我不太关心写入时间,我知道它必须被复制和持久化。但是为什么要花这么长时间阅读呢? 576,000 个 17 字符的字符串键在内存中应不超过 11.5mb,并且值仅为单个字符,将被忽略。 Reliable Collections 不是缓存在 ram 中吗?遍历具有相同值的常规字典需要 13 毫秒。
然后我在一个空字典上调用了ContainsKeyAsync 576,000 次(在 1 个事务中)。这花了 112 秒。在任何其他数据结构上尝试这个可能需要大约 0 毫秒。
这是在本地 1 节点集群上。部署到 Azure 时,我得到了类似的结果。
这些结果可信吗?我应该检查任何配置吗?我做错了什么,还是我的期望非常不准确?如果是这样,是否有更适合这些要求的东西? (约 100 万个小键,无值,持久事务更新)
【问题讨论】:
-
你可以使用 AddRange 命令之类的东西吗?在它之后 CommitAsync?我对经典数据库有类似的经验......如果单独保存更多实体 - 时间比 AddRange 命令长得多......
-
IReliableDictionary 没有这样的 AddRange 批量插入方法docs.microsoft.com/en-us/dotnet/api/… 但比起初始插入,我更关心读取速度。
-
您不仅可以读取数据,还可以读取数据。请仅检查读取数据并测量延迟:
-
IAsyncEnumerable
> enumerable = await dictionary.CreateEnumerableAsync(tx);