Why use ConcurrentQueue in this case?

I am watching Roslyn September 2012 CTP with Reflector, and I noticed that the SlidingTextWindow class has the following:

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; } // ... } 

I believe the purpose of this class is to provide quick access to substrings of input text using char[] characterWindow , starting at 2048 characters at a time (although characterWindow can grow). I believe this is because it’s faster to take substrings of character arrays than strings, as Eric Lippert shows on her blog .

The SlidingTextWindow class is created each time an instance of the Lexer class is created each time a SyntaxTree.ParseText call is SyntaxTree.ParseText .

I do not understand the purpose of the arrayPool field. Its only use in this class is the constructor and Dispose method. When calling SyntaxTree.ParseText , there seems to be only one instance of the Lexer class and the SlidingTextWindow class. What advantage is achieved by placing characterWindow when deleting an instance and trying to delete a characterWindow when creating an instance?

Perhaps someone from the Roslyn team can help me figure this out?

+6
source share
1 answer

The advantage is that the pressure in the manifold is reduced, which positively affects the overall performance.

The .NET garbage collector is, of course, a general-purpose garbage collector. The distribution life patterns of both the compiler object and the IDE are very different from the templates of your mid-sized business application, and they tend to stress the GC in unusual ways.

If you look everywhere in Roslyn, there are many places where small arrays are cached and reused later, rather than allowing the GC to identify them as short-lived junk and return them immediately. Empirical experiments show that this provides a measurable improvement in performance.

I do not recommend doing this in my own application if your profiling does not indicate that you have a measurable performance problem related to collection pressure. For the vast majority of applications, the GC is very well tuned, and the advantage of the merge strategy is not worth the significant cost.

+16
source

Source: https://habr.com/ru/post/952457/


All Articles