当前位置: 首页 > 科技观察

我们什么时候应该谈论性能?

时间:2023-03-17 22:00:45 科技观察

本文转载自微信公众号“JeffckyShare”,作者Jeffcky。转载本文请联系JeffckyShare公众号。个人认为表演不能一蹴而就。需要结合实际业务有一个大概的评估或者预期,比如数据量的大小。如果预计短时间内不会达到性能瓶颈,也不必想太多,或者根据自我想象也有可能。有性能问题,所以大张旗鼓落入自觉流,最后可能落得苦不堪言。项目性能考虑之前个人写过一个版本的Excel导入导出,并没有使用相应的开源组件,因为导出导入逻辑并不复杂,不涉及单元格拆分,包含图片,下拉框等.,不过也好办没有难度,借助NPOI或者EPPLUS工具就可以满足了。于是我尝试进一步重构之前封装的Excel导入导出,主要解决之前遗留的问题:第一:表头列和实体属性列的顺序必须是一一对应的;第二种:导出由于Excel中单个sheet行的限制,超过一定的行数,必须重新建sheet。第三:大量使用反射。如果有多张Sheet,每张Sheet的行数稍多,会有一定的性能瓶颈。以上两点都可以轻松解决。这里我们忽略它。问题出在第三点,因为泛型的使用会为对象读取的每一行反映出来,同时获取它的实例属性并赋值,这里可以提高性能。接下来,我们将通过一个简单的例子来演示如何提高反射性能。当然,还有其他的解决办法。这里我只介绍我个人提高反射性能的方案。像一些开源组件,我们通过属性来标识属性,属性名和header列匹配,顺序不需要保持一致。同样的,基于上面的属性赋值也可以忽略。在这种情况下,我们想要获取对应实体所标识的属性特征。这里为了方便后续的属性赋值,我们缓存了属性相关的信息,避免频繁的通过反射获取属性信息。接下来,我们来进行属性的赋值和获取。我们以设置值为例,同理获取值,同时以10000为基数进行验证,然后增加这个基数,如下测试实体publicclassTest{publicintId{get;set;}publicstringName{get;set;}}反射属性赋值示例,如下:typeof(Test).GetProperty("Id");varpropertyNameInfo=typeof(Test).GetProperty("Name");foreach(vartestintests){propertyIdInfo.SetValue(test,1);propertyNameInfo.SetValue(test,"jeffcky");}Console.WriteLine($"反射赋值耗时:{stopWatch.ElapsedMilliseconds}ms");}当然根据笔记本的配置和使用的非标准耗时方案,结果会有所不同,但基本上可以判断反射时间会超过20ms接下来,我使用delegate方法直接调用property的Set方法,看性能会不会提升);varsetId=(Action)Delegate.CreateDelegate(typeof(Action),null,typeof(Test).GetProperty("Id").GetSetMethod());varsetName=(Action)Delegate.CreateDelegate(typeof(Action),null,typeof(Test).GetProperty("Name").GetSetMethod());foreach(vartestintests){setId(test,3);设置名称(测试,“jeffcky”);}控制台。WriteLine($"Delegatedassignmenttime-consuming:{stopWatch.ElapsedMilliseconds}ms");}接下来我们对比反映10000个数据属性赋值,通过多次运行,调用delegate赋值,看看到底有多耗时。基本上可以控制在5ms以内。想想,差距还是有点大。接下来我们直接把数据量增加到100万,看看差距。结果是显而易见的。通过反射需要1s以上,委托赋值控制在几十ms以内。如果再加上属性的数量和属性值的获取,耗费的时间必然会再次增加。为什么很多人说反射性能差,因为引入反射会通过以下步骤造成性能的巨大损失。一:检查调用的方法是否存在?第二:检查其安全性和访问可见性。第三:检查签名,确保提供的参数个数和类型与方法定义签名一致。第四:求解参数。本文并没有强调不能使用反射,网上也有很多讨论,或者老话说的好,根据业务实际情况,具体分析,不要只看整体性能。比如快递行业,进出口业务非常正常,进口数量也很大。对于这种情况,我们是不是可以考虑通过结构体存储数据呢?一切从实景出发。那么问题来了,写这篇文章的目的是什么?