Dot-Net

序列化性能差的可能解決方案

  • August 30, 2017

我最近使用程序外會話狀態對 ASP.NET 應用程序進行了一些性能測試和分析——在 Web 場上使用會話狀態時這是必要的,以便可以在任何 Web 伺服器上檢索狀態,例如,如果後續HTTP 請求到達不同的伺服器,因為會話不是“粘性”或原始伺服器已關閉等。

令我驚訝的是,當我以滿負荷執行 Web 伺服器並分析 CPU 使用率時,大約 99% 的 CPU 時間都花在了序列化和反序列化會話狀態上。隨後我們實現了一個定制的“記憶體”狀態伺服器;這總是序列化狀態,但也將狀態保留在記憶體中,這樣如果您使用粘性會話,則大多數情況下都不必反序列化狀態。這將伺服器吞吐量提高了 2 倍;但是,序列化仍佔 CPU 時間的 98% 或更多。

通過在序列化之前“修剪”會話狀態中的對象之間不必要的對象引用,我們在速度上獲得了一些進一步的改進——在反序列化時手動修復引用。這將速度提高了 10-20% 左右。這裡的原因是,一些性能損失是由於內置的序列化必須遍歷對象指針的圖,這變成了具有更多指針的更複雜的任務。

繼續調查,我們為我們的一些類編寫了定制的序列化常式,而不是依賴於 .Net 的內置序列化。我們發現性能大大提高了大約50 倍。似乎大部分 CPU 負載是由內置的 .Net 序列化引起的,而由於依賴於使用反射來遍歷對象指針/圖形和提取欄位數據,這反過來又很慢。

將我們的性能提高 50 倍是非常誘人的,從而大大降低了 Web 伺服器硬體要求(功率要求降低了一個較小但仍然很重要的因素)。目前的選項是:

1)編寫自定義序列化。由於任務的複雜性和它產生的維護成本,這是一個問題,也就是說,對類狀態的任何更改都需要對序列化/反序列化常式進行更改。

2)一些第三方解決方案。也許某些產品會在建構時自動生成狀態保存/載入程式碼,從而無需使用反射。

我很想知道是否有人知道第三方解決方案,或者遇到過這個問題,因為我沒有從網際網路搜尋中找到任何提及。

更新:有些人建議在預設內置序列化和純定制序列化常式之間提供一種中間解決方案。這個想法是你為那些影響性能最大的類實現定制的序列化,例如覆蓋ISerializable。這是一種有趣且有前途的方法;但是,我仍然認為可以完全替代內置序列化,而無需編寫和維護任何自定義程式碼——這不能在執行時完成,因為查詢對象和訪問私有數據需要反射。但理論上可以對已建構的程序集進行後處理並註入新方法作為額外的建構步驟。一些分析器使用這種方法在由 C# 編譯器建構後將分析程式碼注入到程序集中。

不幸的是,我只知道選項一和 tbh 可能會開始變得非常痛苦。

但它只做你想做的事,所以它會盡可能快。

祝你好運。

另一種選擇是在伺服器端回發上未觸及的所有控制項上積極禁用 ViewState。

引用自:https://stackoverflow.com/questions/1487724