Như Jim Mischel đã đề cập - không thể thực hiện tra cứu đơn lẻ để thay đổi giá trị mặt hàng của từ điển. ConcurrentDictionary.AddOrUpdate
phương pháp làm nhiều hơn là một hoạt động tra cứu (nguồn phản ánh):
public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
{
TValue local2;
if (key == null)
{
throw new ArgumentNullException("key");
}
if (updateValueFactory == null)
{
throw new ArgumentNullException("updateValueFactory");
}
do
{
TValue local3;
while (this.TryGetValue(key, out local3))
{
TValue newValue = updateValueFactory(key, local3);
if (this.TryUpdate(key, newValue, local3))
{
return newValue;
}
}
}
while (!this.TryAddInternal(key, addValue, false, true, out local2));
return local2;
}
Tôi đã thực hiện thử nghiệm hiệu suất với từ điển đồng thời và ditcionary đơn giản: mở rộng AddOrUpdate
cho IDictionary:
public static class DictionaryExtensions
{
public static void AddOrUpdate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue initValue, Func<TKey, TValue, TValue> updateFunc)
{
TValue value;
value = dict.TryGetValue(key, out value) ? updateFunc(key, value) : initValue;
dict[key] = value;
}
}
Kiểm tra:
static void Main(string[] args)
{
const int dictLength = 100000;
const int testCount = 1000000;
var cdict = new ConcurrentDictionary<string, int>(GetRandomData(dictLength));
var dict = GetRandomData(dictLength).ToDictionary(x => x.Key, x => x.Value);
var stopwatch = new Stopwatch();
stopwatch.Start();
foreach (var pair in GetRandomData(testCount))
cdict.AddOrUpdate(pair.Key, 1, (x, y) => y+1);
stopwatch.Stop();
Console.WriteLine("Concurrent dictionary: {0}", stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
foreach (var pair in GetRandomData(testCount))
dict.AddOrUpdate(pair.Key, 1, (x, y) => y+1);
stopwatch.Stop();
Console.WriteLine("Dictionary: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
static IEnumerable<KeyValuePair<string, int>> GetRandomData(int count)
{
const int constSeed = 100;
var randGenerator = new Random(constSeed);
return Enumerable.Range(0, count).Select((x, ind) => new KeyValuePair<string, int>(randGenerator.Next().ToString() + "_" + ind, randGenerator.Next()));
}
Kết quả thử nghiệm trên môi trường của tôi (mili giây):
ConcurrentDictionary: 2504
Dictionary: 1351
Vì vậy, bạn đang cố gắng loại bỏ một trong các lần tra cứu trong trường hợp thêm hoặc cập nhật? – mydogisbox
Từ điển đồng thời có vẻ khá hiệu quả trong nhiều trường hợp, bạn đã kiểm tra xem nó có cung cấp đủ hiệu suất cho kịch bản của bạn không? – Alex
bạn có thể sắp xếp các khóa-giá trị không? Tôi đoán hầu hết sẽ là O (n log n), do đó bạn có thể phải kiểm tra hiệu năng tốt nhất – Carsten