所以我有一个Dictionary<Type, ...>
,它已经成为一个紧密循环的瓶颈。我想取消使用Type
作为键。我很幸运,最终在该词典中作为键的所有类型都实现了我可以更改的特定接口,并且我想将其更改为抽象基类。
我认为我最终想要做的事情是这样的:
public abstract class MyBaseType
{
public virtual int TypeId { get; }
}
然后,我将以某种方式使从此自动派生的类递增TypeId。这可以自动进行吗?所以我不必为每个数字都专门设置一个数字吗?
我想避免的事情:
public class MyDerived : MyBaseType
{
public override int TypeId => 0;
}
public class MyDerived2: MyBaseTYpe
{
public override int TypeId => 1;
}
...etc
有什么想法吗?
编辑:
是对类型的查找导致了我的瓶颈。将此类型更改为Type
之外的类型是否真的可以给我带来什么好处?
GetHashCode()
上的Type
才成为瓶颈?
答案 0 :(得分:0)
我最终做了(非常重复)的工作,将密钥降低到一个整数,并且速度没有得到太大改善。这说明我对执行的工作成本抱有不切实际的期望。我将研究线程化作为查看改进的另一种方法。
答案 1 :(得分:0)
这是否可以自动进行?所以我不必为每个数字都专门设置一个数字吗?
否。
将其更改为
Type
之外的其他类型实际上能给我带来什么好处吗?
您为什么不尝试找出答案?设置一个简单的测试来比较不同的关键性能非常简单。
如果您不愿意这样做,则会发现int
键 的性能比Type
键要好;在int
的情况下,性能要快两倍以上。
但是该测试最有意义的结果是,在我的机器上,对于int而言,在40毫秒内执行了1 677 000次查找,对于类型而言,在80毫秒内进行了略微查找。这简直是令人难以置信的快速(并且不要忘记那些时间也包括测试键查找)。如果这是您的瓶颈,那么您需要开始思考以某种方式并行化您的工作。
基准代码:
static void Main(string[] args)
{
var d1 = new Dictionary<int, object>();
var d2 = new Dictionary<Type, object>();
var keys1 = new List<int>();
var keys2 = new List<Type>();
var counter = 0;
var types = Assembly.GetAssembly(typeof(int)).GetTypes();
foreach (var t in types)
{
d1.Add(counter, null);
keys1.Add(counter++);
d2.Add(t, null);
keys2.Add(t);
}
//warmup run. JITTER
benchMarkDictionary(d1, keys1);
//good runs
for (var repetition = 0; repetition < 10; repetition++)
{
Console.WriteLine($"Test #{repetition} --------");
Console.WriteLine($"int key: {benchMarkDictionary(d1, keys1)}");
Console.WriteLine($"type key: {benchMarkDictionary(d2, keys2)}");
}
}
static long benchMarkDictionary<TKey, TValue>(
Dictionary<TKey, TValue> dict,
IList<TKey> keys)
{
var count = dict.Count;
TValue result = default(TValue);
var watch = new Stopwatch();
watch.Start();
for (var lookups = 0; lookups < count * 1000; lookups++)
{
result = dict[keys[lookups % count]];
}
watch.Stop();
Console.WriteLine(result);
return watch.ElapsedMilliseconds;
}