This method shows up in OOP allocations in the scrolling speedometer test. This method is invoked to create runes for text sequences for strings. The standard case is that there aren't any multi-char runes in a string, in which case AbstractVirtualCharService.CreateVirtualCharSequence doesn't end up using the ImmutableSegmentedList in the result it creates. This means that we can reuse this builder and it's underlying array after it's been cleared out.
This shows up as around 2.0% of allocations in out OOP in the scrolling speedometer test.
This method was calling ImmutableList.AddRange giving it the result of a Select linq expression. The underlying ImmutableList code doesn't end up special casing that collection type, and thus creates a FallbackWrapper around the enumeration. The FallbackWrapper.Count method uses Enumerable.ToArray to cache a collection object, which ends up
1) doing the double resize allocation dance pass until done
2) resizing that final array
This essentially means we've allocated around 3x the amount of memory needed to hold our documentids. Instead, if we use a pooled list, we can generally avoid the allocations completely (the ImmutableList code instead creates a ListOfTWrapper around our List which doesn't need to allocate)
This method is showing up as around 0.8% of allocations in the typing section of the csharp editing speedometer test.
Saw this in a scrolling speedometer profile, only 0.3%, but it's trivial to remove. They don't publicly expose a struct based enumerator, but they do expose an indexer, so it's easy enough to use that to walk over the collection.
It's pretty common for this array to exceed the size threshold supported by ArrayBuilder (128). For the files I'm testing on, the size supported by SharedPools (512) works much better.
Noticed this due to allocations in the editor's scrolling speedometer test, where it was showing up as 1.5% of allocations during scrolling.
Noticed this while looking at a pooling issue in related code. The issue here is that the code found a case sensitive index, but was still returning a value based on the case insensitive index in one of the code paths.
Also, made a slight perf optimization to start the case sensitive search at the already located case insensitive search index.
* Reduce lock usage during EditDistance.GetEditDistance and BKTree.Find
The SimplePool and ArrayPool classes previously used always locked on Allocate/Free which is showing up in a trace David Kean referred us to. Instead, as the char arrays being allocated are typically quite small, utilize the stack for these temporary char array locations when possible, falling back to heap allocating in the rare occasions where it's not.