2014-09-21 59 views
7

據我所知,Roslyn的預發佈版本實現了Eric Lippert在this excellent blog post中描述的不可變樹。然而,這篇文章的結尾是:Roslyn的發佈版本如何實現不可變樹?

「成本是這個系統很複雜,如果紅色外牆變大,會消耗大量內存。我們目前正在做實驗,看看是否可以減少一些成本不會失去好處。「

我想問一下發布版本的結果是什麼。我已經開始檢查Roslyn sources,但代碼相當複雜。

我感興趣的是關於上述成本的低級設計結果。

  1. 根據紅色/綠色節點進行單個編輯的成本是多少?
  2. 對其他操作進行了哪些優化(例如刪除,撤銷)?
+1

我認爲使用這個更容易:http://source.roslyn.codeplex.com/#Microsoft.CodeAnalysis/Syntax/SyntaxNode.cs,849dc6029695ef7b – MarcinJuraszek 2014-09-21 20:06:32

+1

也可以看一看[BCL immutable collections]( http://channel9.msdn.com/posts/Erik-Meijer-Immo-Landwerth-and-Andrew-Arnott-Immutable-Collections-for-NET)的靈感來自Roslyn紅/綠樹。 – DaveShaw 2014-09-21 20:21:00

+0

@DaveShaw,我快速瀏覽了鏈接,並會觀看視頻。然而,描述頁面沒有提及樹,但它確實提到了許多其他的集合類型。 – bright 2014-09-21 20:23:39

回答

6

有一個美妙的外觀在羅斯林對論壇在這裏的表現和實現不可變的樹木被VSadov:https://roslyn.codeplex.com/discussions/541953

在高層次上,他討論了併發性,綠色節點的重複數據刪除,終端的重複數據刪除以及這些樹中字符串的重複數據刪除。

他還談到了紅樹的懶惰。在每次文本更改後計算紅色樹,而不是在有人請求紅色樹時計算。

最後,他討論了紅樹和它的弱點。我從未使用過或看過WeakReference類,VSadov很好地概述了它在紅色樹中的使用情況。基本上,垃圾收集器被允許清理紅色樹的部分,並且如果需要可以在以後重新創建。我對實現並不熟悉,但Eric Lippert指出,紅色的樹立面可能導致大量的內存佔用。我想這些WeakReferences幫助緩解這個問題在一定程度上。

+0

謝謝,我接受了你的回答。不過,如果能夠得到Undo實施的明確答案,那就太好了。 – bright 2014-09-23 07:14:34

+3

你關於弱參考的假設是正確的。 – 2014-09-23 21:12:38

2

目前我們仍在做與Eric所描述的基本相同的事情。我們嘗試了一些實驗,但發現API清晰度的成本太高而無法支付。相反,我們做出的主要改變是通過將SyntaxToken轉換爲紅色模型中的結構來減少堆分配和GC成本。這是顯着的節省,因爲在平均源文件中,語法樹中大約一半的節點是終端(SyntaxToken s)。綠色節點不是結構體,但是另一方面,因爲它們不包含父指針或位置,所以它們被禁用 - 我們共享所有相同節點(相同的瑣事和文本)的綠色節點的相同實例。

我不確定編輯的「成本」是什麼意思。時間/空間/複雜的/ etc。一般來說,我們有一個增量詞法分析器,它重新掃描受編輯影響的區域。然後我們有一個增量解析器,它在最好的情況下重新解析與新鬆散令牌相交的語句,然後重新構建綠色樹的「脊柱」回到根,同時重新使用綠色的其餘部分樹中的節點。根據定義,任何紅色節點都不可重複使用。新樹有一個新的根節點,它可以從任何其他節點訪問。

在編譯器中沒有進行其他優化。撤消後,我們在IDE中重新使用緩存樹,但我不確定。

+0

我明白SyntaxNode ==紅色節點,GreenNode ==綠色節點。 SyntaxToken如何適合樹結構? – bright 2014-09-22 06:29:24

+0

因此,對於撤消,有一個完整的緩存樹,即每個單個字符插入的新樹?這似乎過於昂貴,請你澄清一下嗎? – bright 2014-09-22 08:51:10

+0

每個編輯都有一個「新樹」,但請記住,大多數綠色節點會在連續編輯中共享。如果樹深度爲'h',那麼平均只有新的O(h)綠色節點被創建。在樹的每個版本中,* *可能是一個不同的紅色節點,但是紅色節點是懶惰地創建的,並且大部分時間IDE實際上並沒有實現許多紅色節點,因爲它稍微有效在快速連續編輯的情況下延遲。 – 2014-09-23 03:52:50