什么时候我们应谈及性能?
【導讀】實際項目開發中、有部分童鞋可能無時無刻都在關注性能,那么我們到底應該什么時候關注性能呢?
個人以為,性能并非一次性就可完全成全,需結合實際業務有一個大致評估或預期,比如數據量大小,若預期短暫并不會達到性能瓶頸,大可不必過度考慮,又或者根據自我假想可能存在性能問題,于是大張旗鼓陷入自我意識流,最終可能結果吃虧反而不討好
項目性能考慮
此前我個人寫過一版Excel導入和導出,并未使用對應開源組件,因為導出和導入邏輯并不復雜,不涉及單元格拆分、包含圖片、下拉框等等,但處理起來也并沒有什么難度,借助NPOI或EPPLUS工具皆可滿足
于是我嘗試將此前封裝Excel導入和導出做了進一步重構處理,主要為解決此前遺留問題:
其一:表頭列和實體屬性列順序必須一一對應
其二:導出由于Excel單個Sheet行有限制,超出一定行,必須重建Sheet
其三:大量使用反射,若存在多個Sheet,且每個Sheet行數量稍微巨大,則存在一定性能瓶頸
如上兩點可以簡單解決,這里我們忽略,問題在于第三點,因為使用泛型,針對每一行讀取都會反射對象,同時也要獲取其實例屬性并賦值,這里我們完全可以改善下性能
接下來,我們通過一個簡單例子,來演示如何改善反射性能,當然,也還有其他方案,這里我只介紹我個人的方案
反射性能改善
如一部分開源組件一樣,我們通過特性標識屬性,屬性名稱和表頭列匹配,順序無需一致,同樣,屬性可忽略賦值
基于上述情況,我們要獲取對應實體所標識的屬性特性,這里為便于后續屬性賦值,我們緩存屬性相關信息,避免頻繁通過反射獲取屬性信息
接下來,我們來到屬性賦值和獲取,我們以設置值為例,獲取值同理,同時以1萬作為基數來驗證,然后以此基數遞增,如下測試實體
反射屬性賦值示例,如下:
static?void?ReflectionExample(int?count) {var?stopWatch?=?new?Stopwatch();stopWatch.Start();var?tests?=?Enumerable.Repeat(new?Test(),?count).ToList();var?propertyIdInfo?=?typeof(Test).GetProperty("Id");var?propertyNameInfo?=?typeof(Test).GetProperty("Name");foreach?(var?test?in?tests){propertyIdInfo.SetValue(test,?1);propertyNameInfo.SetValue(test,?"jeffcky");}Console.WriteLine($"反射賦值耗時:{stopWatch.ElapsedMilliseconds}ms"); }當然,根據筆記本配置以及所使用耗時方案不標準,結果會存在差異,但基本可判斷反射耗時會有20ms以上
接下來,我使用委托方式來直接調用屬性Set方法,看看性能是否會有改善
static?void?DelegateExample(int?count) {var?stopWatch?=?new?Stopwatch();stopWatch.Start();var?tests?=?Enumerable.Repeat(new?Test(),?count).ToList();var?setId?=?(Action<Test,?int>)Delegate.CreateDelegate(typeof(Action<Test,?int>),?null,?typeof(Test).GetProperty("Id").GetSetMethod());var?setName?=?(Action<Test,?string>)Delegate.CreateDelegate(typeof(Action<Test,?string>),?null,typeof(Test).GetProperty("Name").GetSetMethod());foreach?(var?test?in?tests){setId(test,?3);setName(test,?"jeffcky");}Console.WriteLine($"委托賦值耗時:{stopWatch.ElapsedMilliseconds}ms"); }接下來,我們對比反射1萬條數據屬性賦值,看看耗時情況怎樣
通過運行多次,通過調用委托賦值其耗時基本可控制在5ms以內,想想差距還是有點大,接下來我們將數據量直接上升到100萬看看其差距
結果顯而易見,通過反射耗時將超過1s,而委托賦值則控制在幾十ms,如果再加上屬性的個數和獲取屬性值,耗時時間勢必將會再一次拉大
為何很多人都說反射性能很差,因為引入反射會通過如下幾步對性能有巨大損耗
其一:檢查所調用方法是否存在
其二:檢查其安全性和訪問可見性
其三:檢查簽名,確保所提供的參數和類型的數量與方法定義簽名一致
其四:解出參數
此文意非強調不能用反射,網上討論也很多,還是老話,根據實際業務情況,具體分析,別整體就惦記和揪著性能不放,比如針對快遞行業,導入和導出操作可謂再正常不過,其導入數量也是龐大,對于此種情況,我們是否可考慮通過結構體存儲數據呢?一切皆通過實際場景出發。
那么問題來了,寫本文的目的是什么呢?
?????時常自我多學習,多思考,多嘗試,多積累是否存在更好解決方案,我們都可明顯覺察,玩來玩去就那么點語法,為什么別人就能玩出不一樣的花樣,問題在哪里?
總結
以上是生活随笔為你收集整理的什么时候我们应谈及性能?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RabbitMQ 入门:1. Messa
- 下一篇: 数据写入规则IBufferWriterT