我正在使用Reflector查看Roslyn September 2012 CTP,我注意到SlidingTextWindow类具有以下内容:
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。
每次实例化SlidingTextWindow
类时都会实例化Lexer
类,每次调用SyntaxTree.ParseText
时都会发生这种情况。
我不明白arrayPool
字段的用途。它在此类中的唯一用法是在构造函数和Dispose方法中。调用SyntaxTree.ParseText
时,似乎只创建了Lexer
类和SlidingTextWindow
类的一个实例。通过在放置实例时将characterWindow
排入队列并在创建实例时尝试使characterWindow
出列,可以获得什么好处?
也许Roslyn团队的某位成员可以帮助我理解这一点?
答案 0 :(得分:17)
优点是收集压力降低,这对整体性能有积极影响。
.NET垃圾收集器当然是一个通用的垃圾收集器。编译器和IDE的分配和对象生存期模式与平均业务线应用程序的模式完全不同,并且它们倾向于以不寻常的方式强调GC。
如果您在整个Roslyn中查看,有许多地方会缓存小型数组并在以后重新使用,而不是让GC将它们识别为短期垃圾并立即回收它们。经验实验表明,这可以带来可衡量的绩效改善。
我不建议您在自己的应用程序中这样做,除非您的分析表明您在收集压力上存在可衡量的性能问题。对于绝大多数应用程序而言,GC的调整非常好,并且汇集策略的好处不值得花费相当大的成本。