从一次重复造轮子中发现的一个性能优化思路。
起因是这样的,自己出于各种原因,一方面是兴趣,一方面是目前市面上没有找到比较合适的开源项目。
所以自己重复造轮子写了一个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的区别。
为什么会这样呢?
就是因为有些时候我们进行验证所消耗的性能反而高于抛出特定异常所消耗的性能。
这样,我们在有些时候就可以利用这些特定异常来跳过判定过程,以达到提速的目的。
希望能对大家有所帮助 性能优化 新思路 c#
[解决办法]
我倒是比较感兴趣“大概有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还是最好的,代码更简洁优美,这种内存操作,性能从来不是问题,优化的意义不大。
[解决办法]
可以考虑一下你的样本
比如说
你的dic中的数据是123 你要返还的数据的样本是2141
你的两种不同的代码的执行是
第一种 带containskey的执行
判断是否有key为2
赋值key为2
判断是否有key为1
赋值key为1
判断是否有key为4
初始化key为4
赋值key为4
判断是否有key为1
赋值key为1
总共9步
第二种 try的
赋值key为2
赋值key为1
赋值key为4
key为4出错
初始化key为4
赋值key为4
赋值key为1
总共7步
以此为例,你的样本对性能的影响很大,所以暂时看来 论据不足以支持论点
不足以得出try catch比containskey的性能要优化。现在可以得出的结论是,在预知样本命中率显著
高于非命中的时候try catch比containskey方案要优化,并不能绝对保证性能的优化
有待于楼主给出抽样 样本 来实际反驳
--------------------------------------------------------------------
另外从执行角度而言,try等于是在method(也可能是其他的如property)层面又加了一层statement,
也就是多了一层副本,如果出错可以保证回滚的机制,本身会有一定的性能开销
,如果try中间的语句较多,相信也会很大程度上影响测试结果
[解决办法]
提个观点,大家探讨下是好的,但是楼主貌似有点小得瑟了啊。
传统之所以是传统,就是因为它的普适性,它确实是人们在生产中总结出来的精华。
你的优化方案,使用try catch这种重型武器,就为了干这点小事,有些过了。
代码量更大,思路更绕是否值得?
而且,好几个人包括我都质疑了你这样做是否能优化性能,恕我直言,你在一楼的测试方案,简直就是粗鄙不堪的。
命中率在这个场景中,是非常重要的一个因素,提出来了,你也不能正面应对。