使用 JointCode.Shuttle 提升跨 AppDomain 通訊的性能

JointCode.Shuttle 是一個用於進程內 AppDomain 間通訊的服務架構(不支持跨進程),它旨在取代運行時庫提供的 MarshalByrefObject 的功能。git

本文比較了 MarshalByrefObject 與 JointCode.Shuttle 的跨 AppDomain 對象訪問的性能。github

背景知識緩存

咱們知道跨 AppDomain 調用的性能是十分低下的,由於在這種狀況下對象之間的交互不是直接的,而是要穿越一個邊界 (AppDomain)。安全

爲了穿越這個邊界,首先須要將對象轉換(術語稱爲「marshal」,即封送)成一個能夠傳輸的形態(好比,在 .NET Remoting 中對象將被打包成一個可序列化的 ObjRef 實例——MarshalByrefObject 中的 ByRef 指的就是 ObjRef 這種形態);而後,當數據流到達目標 AppDomain 時,還要執行解封 (unmarshal) 操做將其還原爲內存中的對象。這個過程是很是耗時的,由於其中可能涉及到各類反射、序列化/反序列化、安全檢查等等。能夠想象獲得,若是一個程序頻繁發起跨 AppDomain 調用,那麼它的性能恐怕將會受到嚴重影響。架構

好在咱們通常不須要和 AppDomain 打交道,所以也沒必要太多關注它。然而,有的時候咱們確實不得不使用 AppDomain。好比說在插件環境下,咱們有可能須要動態加載/卸載程序集,在這種狀況下 AppDomain 是不二選擇,由於咱們知道在 .net/mono 中,程序集是不能單獨卸載的,只能隨着 AppDomain 一塊兒卸載。性能

爲了提升 AppDomain 間通訊的性能,做者開發了 JointCode.Shuttle。測試

測試spa

爲了比較 JointCode.Shuttle 和 MarshalByrefObject 的跨 AppDomain 調用性能,而且儘可能瞭解可能會影響性能的各個因素,我編寫了一個測試。該測試向咱們展現了兩種類型的結果:.net

  • 反覆建立遠程服務對象並調用對象方法:這是爲了從總體上比較兩者的調用性能(包括建立對象和調用方法的開銷)。
  • 建立遠程服務對象,並將其緩存到一個本地字段中,而後反覆調用對象方法:這是單純爲了比較兩者的遠程方法調用性能(僅僅測試調用方法的開銷)。由於方法調用時可能須要傳遞各類不一樣類型和數量的參數,這些都會影響最終性能。須要特別指出的是,這種作法僅僅是爲了方便測試,在實踐中是不能將遠程服務對象的引用緩存到字段的。由於遠程服務對象的生命期受控於遠端,它有可能在遠端已經超時失效並被垃圾回收,而本地調用者對此並不知情,仍舊繼續調用其方法,此時將會拋出異常。

 

下面這張圖是部分測試結果:插件

 JointCode.Shuttle與MarshalByObject性能對比

若是您對測試代碼自己感興趣,可移步前往 此處 下載測試源碼(測試名稱:ShuttleDomain性能測試)。

相關文章
相關標籤/搜索