Dot-Net
流暢的介面是否會顯著影響 .NET 應用程序的執行時性能?
我目前正忙於為現有技術實現一個流暢的介面,這將允許類似於以下程式碼段的程式碼:
using (var directory = Open.Directory(@"path\to\some\directory")) { using (var file = Open.File("foobar.html").In(directory)) { // ... } }為了實現這樣的結構,需要類來積累參數並將它們傳遞給其他對象。例如,要實現該
Open.File(...).In(...)構造,您需要兩個類:// handles 'Open.XXX': public static class OpenPhrase { // handles 'Open.File(XXX)': public static OpenFilePhrase File(string filename) { return new OpenFilePhrase(filename); } // handles 'Open.Directory(XXX)': public static DirectoryObject Directory(string path) { // ... } } // handles 'Open.File(XXX).XXX': public class OpenFilePhrase { internal OpenFilePhrase(string filename) { _filename = filename } // handles 'Open.File(XXX).In(XXX): public FileObject In(DirectoryObject directory) { // ... } private readonly string _filename; }也就是說,初始範例等語句的組成部分越多,需要創建的對象就越多,以便將參數傳遞給鏈中的後續對象,直到實際語句最終可以執行。
問題:
我對一些觀點感興趣:使用上述技術實現的流暢介面是否會顯著影響使用它的應用程序的執行時性能?對於執行時性能,我指的是速度和記憶體使用方面。
請記住,可能只需要在非常短的時間跨度內創建大量臨時的、保存參數的對象,我認為這可能會給垃圾收集器帶來一定的壓力。
如果您認為有顯著的性能影響,您知道實現流暢介面的更好方法嗎?
一般來說,生命週期非常短的對象正是 GC 處理效率最高的對象,因為它們中的大多數將在下一次次要收集執行時死亡——在任何體面的 GC 實現中,成本次要集合與活動對象的總大小成正比。因此,短期對象的成本非常低,並且它們的分配只意味著向上碰撞一個指針,這很快。
所以我會說:可能沒有顯著的性能影響。
Thomas 非常正確,分代 GC 正是針對這種短期對象的分配和收集進行了優化。然而,像 OCaml 這樣的函式式語言的 GC 比 .NET 更加優化,但是,在將多個參數應用於柯里化函式的等效情況下,它們仍然竭盡全力避免這種情況。具體來說,他們使用一種稱為大步語義的技術,其中編譯器在編譯時刪除所有中間體,因此 GC 永遠不會看到任何這些。
在 .NET 上,值類型很可能讓您自己解決這個問題。