我正在实施我的收藏:
SpecialCollection类:
public class SpecialCollection<TId, TName, TValue> : Dictionary<CompositeKey<TId, TName>, TValue>
{
#region Private fileds
private Dictionary<CompositeKey<TId, TName>, TValue> _baseDictionary = null;
private ReaderWriterLockSlim _readWriteLockSlim = new ReaderWriterLockSlim();
#endregion
#region Constructors
public SpecialCollection()
{
_baseDictionary = new Dictionary<CompositeKey<TId, TName>, TValue>();
}
#endregion
public void Add(CompositeKey<TId, TName> compositeKey, TValue value)
{
_readWriteLockSlim.EnterWriteLock();
try
{
_baseDictionary.Add(compositeKey, value);
}
catch (ArgumentNullException ex)
{
throw ex;
}
catch (ArgumentException ex)
{
throw ex;
}
finally
{
_readWriteLockSlim.ExitWriteLock();
}
}
}
CompositeKey类:
public struct CompositeKey<TId, TName> : IEquatable<Tuple<TId, TName>>
{
public TId Id;
public TName Name;
public CompositeKey(TId id, TName name)
{
Id = id;
Name = name;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
if (this.GetType() != obj.GetType())
return false;
return AreEqual(this, (CompositeKey<TId, TName>)obj);
}
public bool Equals(CompositeKey<TId, TName> other)
{
return AreEqual(this, other);
}
private static bool AreEqual(CompositeKey<TId, TName> a, CompositeKey<TId, TName> b)
{
if (!a.Id.Equals(b.Id))
return false;
if (!a.Name.Equals(b.Name))
return false;
return true;
}
public static bool operator == (CompositeKey<TId, TName> a, CompositeKey<TId, TName> b)
{
return AreEqual(a, b);
}
public static bool operator != (CompositeKey<TId, TName> a, CompositeKey<TId, TName> b)
{
return !AreEqual(a, b);
}
public override int GetHashCode()
{
return Id.GetHashCode() ^ Name.GetHashCode();
}
public bool Equals(Tuple<TId, TName> other)
{
throw new NotImplementedException();
}
}
我遇到了与表现有关的问题。例如,向我的集合添加10000个元素需要9745
毫秒。但是向ConcurrentDictionary添加10000个元素需要4965
毫秒。
如果将30000个元素添加到我的集合中,则需要花费大量时间 - 大约40000
毫秒。
我不知道如何提高性能:(如果有可能,请告诉我如何改善我的收藏的性能?可能是,与CompositeKey类相关的性能?
编辑:
我测试了这样的表现:
ConcurrentDictionary<CompositeKey<int, int>, int> cd = new ConcurrentDictionary<CompositeKey<int, int>, int>();
SpecialCollection<int, int, int> sc = new SpecialCollection<int, int, int>();
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10000; i++)
{
cd.TryAdd(new CompositeKey<int, int>(i, i), i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Start();
for (int i = 0; i < 10000; i++)
{
sc.Add(new CompositeKey<int, int>(i, i), i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
谢谢!
答案 0 :(得分:5)
我自己测试过,性能几乎没有差异。鉴于您的测试代码,性能差异可能是因为您不会在测试之间重置秒表。正如the documentation所说:
当秒表实例测量多个间隔时,Stop方法相当于暂停经过时间测量。随后对Start的调用将恢复从当前经过时间值开始测量时间。使用“重置”方法清除秒表实例中的累计已用时间。
只需在测试之间添加sw.Reset()
。
在我的测试中,我确实使用lock
关键字代替ReaderWriterLockSlim
来获得非常小的性能提升,但它可能是随机的。
答案 1 :(得分:1)
ReaderWriterLockSlim#EnterWriteLock
似乎比简单的C#监视器锁慢得多。由于ConcurrentDictionary
使用简单锁(与并发级别参数一样多),因此这可能是性能问题的根源。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
private static object lock1 = new object();
private static ReaderWriterLockSlim lock2 = new ReaderWriterLockSlim();
public static int DoLock1(int value)
{
lock (lock1)
return value;
}
public static int DoLock2(int value)
{
lock2.EnterWriteLock();
try
{
return value;
}
finally
{
lock2.ExitWriteLock();
}
}
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10000000; i++)
{
DoLock1(i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Reset();
sw.Start();
for (int i = 0; i < 10000000; i++)
{
DoLock2(i);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadLine();
}
}
}