2009-07-22 54 views

回答

2

反射性能很好,它只是確實比靜態代碼多

說你有這樣的代碼片段:

typeof(SomeClass).GetMethod("SomeStaticMethod"). 
Invoke(null, new object[] { 1, 2, 3 }); 

這是與此相同:

SomeClass.SomeStaticMethod(1, 2, 3); 

但它應該是顯而易見的是,第一個有很多工作要做。它必須獲取類型信息,遍歷它以查看是否存在SomeStaticMethod方法,檢查它是什麼類型的方法,在實例上調用該方法,或者如果它是靜態的,則不傳遞對象數組參數,裝箱/拆箱整數在這種情況下也是如此。

這可能是一個非常廣泛的總結,毫無疑問更多的事情正在進行。儘管如此,反射速度仍然很快,並在很多領域使用,從WinForms的數據綁定到ASP中的模型綁定。NET MVC(你對這個站點建立的每一個請求,建立在MVC上,涉及到大量的反射,然而,這個站點非常快,MVC被認爲是一個非常快速的框架)。

1

因爲它涉及在運行時查找的字符串(類型和成員名稱的),以及額外的裝箱/拆箱值類型。

4

上了不起的文章MSDN:Dodge Common Performance Pitfalls to Craft Speedy Applications。基本上,這是一個遲到和早期約束的問題。也就是說,可以在編譯時決定什麼,以及在運行時必須決定什麼。那篇文章...

後期綁定案件 MethodBase.Invoke,DynamicMethod的通過 調用,Type.InvokeMember和 後期綁定代理呼叫(通過Delegate.DynamicInvoke上 代表呼叫)。 所有這些方法都具有比 早期綁定的情況下 顯著負 性能的影響。即使在最好的情況下,它們的典型範圍是 的幅度比最慢的 早期的情況。

他打破了我們進行早期和晚期調用的各種方式的不少性能測試。值得一讀。

1

反射涉及將元數據來解析名稱的標記,它然後使用該令牌進行查找和檢索所需的數據(例如,一個方法令牌用於獲取有關方法的信息,參數.. 。等等)。

由於2個原因,此過程很昂貴。 1-很多查找正在進行中。 2-觸摸通常不會觸及的頁面(冷頁面),其中包含元數據表格。

直接訪問元數據非常昂貴,CLR維護緩存以使此過程更快,並避免在以非反射方式訪問事物時觸及元數據表,但是一旦進入反射狀態,我們會繞過這些緩存並直接進入來源。

16

反射效果並不是很好

這是一個非常加載聲明。 「表現良好」是相對的。與靜態代碼相比,反射式呼叫不會執行,也不會執行。但是,在幾乎所有情況下,.NET中的反射都是非常快的。我無法低估這一點。反思在.NET 1.x和其他語言中得到了不好的聲譽,但是在.NET 2.0+中的反射是,並且很快就出現了

的情況下,99%的「是反映太慢」是一個無關緊要的問題。我懷疑你需要費心衡量一個反射電話對靜態電話的性能影響。

+0

嗯,我在Windows窗體應用程序中使用反射來創建一個動態的用戶界面,我沒有看到任何性能問題。當然,在我不知道的「高性能關鍵」應用程序中可能會有所不同。 – Malcolm 2009-07-22 01:43:50

0

反射在.NET中表現良好 - 它具有的功能。

然而,反思,因爲它已經編譯類型的運行時分析,需要相當多的開銷。一般來說,像靜態類型信息的字符串查詢,以及漫遊類元數據等,都需要一段時間。

這並不是說它真的很慢 - 它只是比完全編譯的海峽方法調用和查找慢得多。它應該是 - 但我真的更多地想到它,因爲在任何系統中,編譯代碼比動態查找信息更快。

5

簡單地說,「反射」執行緩慢是在很寬的毯子底下包含許多功能的地獄。 .NET中的反射有幾個類,每個類都有不同的「性能」級別。首先,使用typeof()運算符實際上是一種反射形式...它查詢CLR元數據的類型。然而,typeof()執行得非常快(在接近空閒時間)。使用其他類型相關的「反射」,如is運算符,sizeof()運算符等也幾乎是免費的(它們基本上就像靜態代碼一樣執行。 )

考慮到指針遍歷和元數據探測的數量,用於檢索類型信息的反射速度比typeof()慢,也是非常非常快的。元數據探測是.NET代碼的一種常見做法,尤其是在處理自定義屬性時。

關於反射的重要性能問題與調用有關。訪問類型信息和讀取元數據的權重相當輕。當涉及動態調用屬性,索引器,方法或通過反射動態構造新類型時,您會獲得數量級的性能優勢。

反射仍然是一個進程內執行,所以在你擔心動態調用的性能下降之前,請確保沒有任何明顯更大的性能瓶頸,如進程間執行,網絡調用(即數據庫,Web服務等)當涉及到性能時,從最大的性能開始,然後從這裏開始。包括動態調用在內的反射通常是從性能角度考慮的最後一件事情。

附錄:

的思想後一點,但如果你需要高度的後期綁定類型成員的動態調用的,你應該看看輕量級代碼生成。使用System.Reflection.Emit命名空間,您可以使用DynamicMethod等實用程序在運行時生成輕量級代碼,以執行早期綁定的調用。對生成的代碼進行緩存可以降低生成代碼的初始成本,使您可以利用早期綁定的性能獲得後期綁定的呼叫。