从一次重复造轮子中发现的一个性能优化思路。
起因是这样的,自己出于各种原因,一方面是兴趣,一方面是目前市面上没有找到比较合适的开源项目。
所以自己重复造轮子写了一个IOC容器。
一开始很简单就是使用Dictionary来进行缓存,使用Reflect进行创建。
在优化过程中,我发现c#中可以用这么一个有趣的写法来进行提升效率。
一开始我的缓存的写法是这样的。
Dictionary<Type, Dictionary<string, RegistObjectContext>()> dic;
if(!dic.ContainsKey(key)){
dic.Add(key, new Dictionary<string, RegistObjectContext>());
}
cDic = dic[key];
而优化后是这样的
try
{
cDic = dic[pType];
}
catch (KeyNotFoundException)
{
dic.Add(pType, new Dictionary<string, RegistObjectContext>());
cDic = dic[pType];
}
在进行100w次运算,优化前和优化后的写法,大概有100-200ms的区别。
为什么会这样呢?
就是因为有些时候我们进行验证所消耗的性能反而高于抛出特定异常所消耗的性能。
这样,我们在有些时候就可以利用这些特定异常来跳过判定过程,以达到提速的目的。
希望能对大家有所帮助
------解决方案--------------------我倒是比较感兴趣“大概有100-200ms的区别”你是怎么测出来的
------解决方案--------------------最好是用TryGetValue
------解决方案--------------------如果是100W次加起来发现有100~200ms差别,那么这基本上就可以认定为没有什么差别。
------解决方案--------------------你的代码有一点费解:
Dictionary<Type, Dictionary<string, RegistObjectContext>()> dic;
if(!dic.ContainsKey(key)){
dic.Add(key, new Dictionary<string, RegistObjectContext>());
}
cDic = dic[key];
为什么插入之后,再查找一遍?直接写
Dictionary<Type, Dictionary<string, RegistObjectContext>()> dic;
cDic = new Dictionary<string, RegistObjectContext>()
if(!dic.ContainsKey(key))
dic.Add(key, cDic);
岂不是更好嘛!
------解决方案--------------------
这么龌龊的回复你也说得出口,
你还记得当初怎么牛逼烘烘的毛遂自荐来当版主的么?
你骂人骂习惯了,累教不改------解决方案--------------------cDic = dic[key];
这个地方,楼主改一下,再测试看看。
try会额外消耗性能,这是肯定的,
但是你第一种多查询了一次。
至于第二种方法,还要看cache命中率,如果很高,第二种还有点优势,但如果命中率比较低,则异常引发次数太多,肯定不行。
不过归根结底来说,TryGetValue还是最好的,代码更简洁优美,这种内存操作,性能从来不是问题,优化的意义不大。
----