前面的三次測試都是在同一個項目內的,既處於同一個程式集。那麼,跨程式集調用會怎麼樣呢?
因為為了保證可維護性,我們會把一些常用操作封裝到類庫中去。然後實際項目開發時,引用該類庫,使得解決方案中存在多重專案。編譯完成後,將會是一個主要的exe和若干個dll檔案,主exe程式集中的代碼會調用dll程式集,既形成了跨程式集調用。
分析跨程式集調用的效能,有助最佳化類庫架構的設計。
一、測試辦法
其實步驟很簡單——
1.重新開啟VS2005。或關閉解決方案。
2.建立一個“Windows應用程式”項目。如“TryPointerCallns2005”。
3.添加項目,選擇上次的“TryPointerCall2005”。現在解決方案中就有兩個項目了。
4.選擇第2步時建立的項目(TryPointerCallns2005),添加引用,將“TryPointerCall2005”加上去。
5.調整項目屬性,允許不安全的代碼。
6.建立一個類(TestCall),將測試代碼全部Copy過來(注意只複製測試代碼,不複製IPointerCall、PointerCall等實現)。
7.修改視窗介面,調用TestCall的測試代碼。
二、測試環境
編譯器——
VS2005:Visual Studio 2005 SP1。
採用上述編譯器編譯為Release版程式,最大速度最佳化。
機器——
HP CQ42-153TX
處理器:Intel Core i5-430M(2.26GHz, Turbo 2.53GHz, 3MB L3)
記憶體容量:2GB (DDR3-1066)
三、測試結果
測試結果如下——
== PointerCallTool.TryIt() ==
寫入程式碼.棧變數: 162
寫入程式碼.棧分配: 168
寫入程式碼.靜態: 164
靜態調用: 160
64寫入程式碼.棧變數: 161
64寫入程式碼.棧分配: 160
64寫入程式碼.靜態: 160
64靜態調用: 162
調用衍生類別: 1118
調用密封類: 1049
調用結構體: 1069
調用基類: 1128
調用衍生類別的介面: 1132
調用密封類的介面: 1135
調用結構體的介面: 1453
基類泛型調用衍生類別: 1769
基類泛型調用基類: 1774
介面泛型調用衍生類別: 2230
介面泛型調用密封類: 2240
介面泛型調用結構體: 1215
介面泛型調用結構體引用: 1127
介面泛型調用基類: 2241
介面泛型調用衍生類別的介面: 2230
介面泛型調用密封類的介面: 2244
介面泛型調用結構體的介面: 2302
可見,在跨程式集調用時,調用密封類、調用結構體不會被即時編譯器(JIT)做內聯最佳化,而被當做普通的虛方法調用。
所以,對於那些要求效能的代碼,應盡量保證在同一程式集內,避免將其放在類庫工程,這樣能儘可能地利用即時編譯器(JIT)內聯最佳化的機會。
(完)
原始碼下載——
http://files.cnblogs.com/zyl910/TryPointerCall_4.rar
目錄——
C#類與結構體究竟誰快——各種函數調用模式速度評測:http://www.cnblogs.com/zyl910/archive/2011/09/19/2186623.html
再探C#類與結構體究竟誰快——考慮棧變數、棧分配、64位整數、密封類:http://www.cnblogs.com/zyl910/archive/2011/09/20/2186622.html
三探C#類與結構體究竟誰快——MSIL(微軟中繼語言)解讀:http://www.cnblogs.com/zyl910/archive/2011/09/24/2189403.html
四探C#類與結構體究竟誰快——跨程式集(assembly)調用:http://www.cnblogs.com/zyl910/archive/2011/10/01/2197844.html