我看Roslyn September 2012 CTP与反射,我注意到SlidingTextWindow类有以下几点:为什么在这种情况下使用ConcurrentQueue?
internal sealed class SlidingTextWindow : IDisposable
{
private static readonly ConcurrentQueue<char[]> arrayPool = new ConcurrentQueue<char[]>();
private int basis;
private readonly LexerBaseCache cache;
private char[] characterWindow;
private int characterWindowCount;
private int characterWindowStart;
private int offset;
private readonly IText text;
private readonly int textEnd;
public SlidingTextWindow(IText text, LexerBaseCache cache)
{
this.text = text;
this.basis = 0;
this.characterWindowStart = 0;
this.offset = 0;
this.textEnd = text.Length;
this.cache = cache;
if (!arrayPool.TryDequeue(out this.characterWindow))
{
this.characterWindow = new char[2048];
}
}
public void Dispose()
{
arrayPool.Enqueue(this.characterWindow);
this.characterWindow = null;
}
// ...
}
我相信这个类的目的是提供输入文本的子快速访问,通过使用char[] characterWindow
,一次从2048个字符开始(尽管characterWindow
可能增长)。我相信这是因为字符数组的子字符串比字符串更快,正如Eric Lippert seems to indicate on his blog。
每次Lexer
类实例化时,SlidingTextWindow
类都会实例化,每次调用SyntaxTree.ParseText
时都会发生这种类。
我不明白arrayPool
字段的用途。它在这个类中的唯一用法是在构造函数和Dispose方法中。当致电SyntaxTree.ParseText
时,似乎只创建了Lexer
类和SlidingTextWindow
类的一个实例。当一个实例处理时排队characterWindow
,并且在创建一个实例时尝试将一个characterWindow
排队,会带来什么好处?
也许有人来自罗斯林团队可以帮助我理解这一点?
是否为减少内存或提高速度(或两者)的主要目的完成小阵列的缓存?是否有如此多的编译器/ IDE所必需的数组,每次创建一个新数组都会占用大量内存?或者是否会通过使用线程安全队列并使多个线程作用于阵列来提高速度? – cubetwo1729
主要是速度和响应速度。 GC在性能方面很有意思 - 它几乎可以免费分配内存,但当GC运行时,您需要付出代价。在某些情况下,如果在编写代码的同时在编辑器中键入字符时发生运行,则GC对键入有明显的影响,并且无法执行完全并发的GC。 我确实想强调Eric所说的 - 我们只在我们看到配置文件中出现特定分配时才这样做。除非我们知道这是特定位置的特定问题,否则我们不会这样做。 –
@JasonMalinowski挑选'ConcurrentQueue'而不是'ConcurrentBag'的任何特定原因? – CodesInChaos