VB6 升級到 .NET 後找出效能瓶頸的證據–Profiling
找出系統效能問題,一直都是開發人員一種心中的痛!
一般來說都知道能準時把功能寫出來,就已經是阿彌陀佛了!
還要再把「效能」考量在程式中?唉呀!先解決眼前的問題吧…
之前討論類似的問題時,有一些客戶會沒辦法理解…
為什麼開發人員會不知道是發生了什麼問題?不是都自已寫的嗎?
團隊會因為各種不同的壓力
(Ex.. 亂押時程、時間不夠、開發人員突然消失找不到、程式開發技術點數不夠… )
因而沒有辦法把 效能問題 的時間留下來進行驗證,再加上沒有寫 Health Model ( Log )
那麼等到上線後發生了問題,往往會沒辦法知道為什麼會慢了。
簡單一點來說就是「沒有時間」or 「沒有人意識到效能的重要性」
平均找出一個效能瓶頸點要花上 1-2 週的時間
那麼團隊有寫 Health Model 就可以馬上找到嗎?
有經驗的朋友馬上就會知道,事情永遠沒這麼簡單…
有 資料 ( 包含 數量和特殊值 )、時間、人數 (看性質) 和 環境 等 各種不同的因素困擾著
自已寫的 Log 記錄?你一定可以知道那一段慢!
但你要知道是 那一個 Method、SQL 語法、元件 ( 含 3rd party) 慢就會是一個非常大的工程
最慘的是,明明就有寫 Log 。但卻還是有人不相信的情況!
總是要團隊找出證據!?還要說明為什麼會變慢嗎?
各位在 .NET 實務上有這樣子的困擾嗎??
若是有的話 請務必考慮用 VS 2010 的 Profiling 來做分析
用工具方式產生的效能分析報表,可以有效提升可信度!
另一方面各是可以收集各種不同維度的報表
--------------- T 公司 實務案例分析 ------------------------------------------------
這次系統是屬於 Client 型的系統 ( Web 系統則是建議要搭配 Load Test )
測試平台分別在 XP 和 2003 平台上,都是 4 核心以上的電腦
而且程式都有做 Health Model
問題一共有兩個!
為什麼在不同的顏色數和平台上會有 10 倍的效能差異 ( 定義是指 0.1 和 0.01 )
另外,當較慢的電腦將程式最小化後速度就會有大幅地提升?
系統是用 VB 6 用精靈的方式移轉到 .NET 平台系統上。
為什麼同樣的程式在 .NET 上會比 VB 6 慢?
怎麼產生效能分析報表可以參考,效能分析的初級開發人員指南
http://msdn.microsoft.com/zh-tw/library/ms182372.aspx
對於有問題的功能用 Profiling 分別在兩種不同的環境中進行錄製操作
首先會比較建議用「呼叫樹狀圖」先看 Hot Path 是那個地方卡最久
從報表中可以看出 XP 和 2003 上的時間上有一個決定性的因素
花費時間在載入的動作上是佔裡面最多的,可立即看出來光是這裡就差了快兩倍
就要特別去看在 2003 中 那個 EventHandler 做了什麼,多增加了 10 倍
第二個就是從 工具中進行效能報表的比對,分別用 執行時間 和 執行時間的百分比
可以看到 以 2003 為基準, XP 上執行超過 1000 個差異單位 ( 這裡用的是執行時間 )
因為 2003 和 XP 分別是用不同的硬體設備和 OS 來執行的,多多少少會有出入
% 可以讓我們在不同的電腦環境中得到相同的分析指標!
除了可以做交叉確認外,更可以將範圍縮小
避免每個人對於程式碼執行速度定義是不一樣的!
其中在執行 ScreenDump 和 EventHandler 的動作差異高達 30%
這有可能代表有程式會造成效能衝擊的 code。
接下來我們針對上面的清單進行 Method 抽查 ( Review )
因為 Method 的速度快與慢完全取決於我們執行了什麼!
所以 Call Stack 的執行效率比例對我們是否找對方向是非常重要的
這裡針對剛剛最有爭議的 EventHandler 進行分析以得知呼叫關係
開啟「函式詳細資料」 ( 可以用 關鍵字 搜尋 )
經程式碼 Review 確認後
細查發現裡面的程式碼為了要可以即時更新介面
這裡用了很多 DoEvent,程式中的寫法是 1 秒鍾執行 20 次同時也更新 20 次介面
( 注:由於 VB6 當時並沒有支援多執行緒的機制,為了要讓程式在執行中也可以更新介面。所以用 DoEvent 強迫讓 Windows 可以重新更新介面 )
這對於團隊要求效能會有非常大的影響。
問題一、相同的 .NET 程式 一般顯示 和 最小化 執行時間差異 10 倍?
由於 .NET 中間會透過 .NET Framework 處理 和 Windows 之間所有的動作 ( 從分析報表可以看到 )
當 介面有顯示在桌面上時, .NET Framework 會處理 介面的更新。
但當 介面最小化的時候,.NET Framework 會認為不需要更新介面的動作,雖然程式都有更新 30 次的資料
在介面更新的次數卻沒有那麼多次。 若是 VB 6 的話則是都會強迫使用到 BitMap 的更新動作。
另外,Windows 的 16 bit 和 32 bit 顏色顯示上也會造成 記憶體的使用量!
在一般非娛樂性工作機上,還是建議使用 16 bit 就可以了!!
( VB6 則不會因為 16 bit / 32 bit 顯示有所差異 )
問題二、由於 語言特性的不同,在程式碼開發規範中也會有不同的建議方式
從效能分析報表來看,效能瓶頸最大的幾乎都是在 介面更新上
而且從現場實機的 CPU 來看 都不超過 30% ( 其他都是躺平 )
從程式運作來看 1 秒中會更新 20 – 30 次的資料到介面上
程式中的介面更新都是強迫用 DoEvent 的方式 ( 這會讓 執行緒中斷 強迫 Windows 更新介面 )
再加上,此系統原本是用 工具精靈轉換成 .NET 程式 都還沒有做過最佳化
建議程式碼要用多執行緒處分別處理介面和資料處理
或是將更新介面的動作改用 批次更新,對於 效能上都會有非常大的改善。
最後整個看完用 VS 2010 Profiling 進行效能分析
希望可以讓各位知道如何應用工具的方式來幫助我們平常的開發工作上。
雖然程式碼都已經寫完了,但開發的工作並沒有停止。
報表提供完整的資訊讓開發人員進行評估,以確保效能調校的「方向」是沒有錯的。
不然就會浪費無謂的時間。
以上的案例不是只有 Windows Client AP 才有幫助,在 Web 上也是可以達到更多分析。
--------------VB6 和 .NET 的架構差異 造成執行效率不同------------------------
VB 6 是屬於原生機器碼執行 ( 和 C++ 一樣 ) 由 OS 平台直接執行程式
不用再透過 .NET Framework 處理過程。
所以,以執行效率來說 VB 6 的啟動 和 介面更新是比較快的。
但也因為如此,會造成 和 OS 相依性過高、記憶體管理的問題。
而 .NET 系統 則是在 OS 和 AP 之間多加了一層中介層 ( CLR )
讓開發團隊可以避免系統直接存取 Windows API 。
讓程式有統一的管理,開發人員就不用再自已去處理底層的程式
不過也因為如此,用同樣更新介面的方式 .NET 會比 VB6 稍微慢一些 。
有關於 CLR 可以參考
http://msdn.microsoft.com/zh-tw/library/8bs2ecf4(v=VS.100).aspx
Managed 執行程序
http://msdn.microsoft.com/zh-tw/library/k5532s8a.aspx
-------------------------------------
參考資料
程式碼剖析工具檢測方法資料檢視
http://msdn.microsoft.com/zh-tw/library/dd255375.aspx
模組檢視 - 程式碼剖析工具:檢測資料