-
-
Notifications
You must be signed in to change notification settings - Fork 497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eliminate allocations from CharacterAnalyzer<StringLookAheadBuffer> #957
Eliminate allocations from CharacterAnalyzer<StringLookAheadBuffer> #957
Conversation
Implement updated ObjectPool from Microsoft.Extensions.ObjectPool
Note that this PR uses the same benchmark introduced in #953 and #954. So if / when one of these PRs merge, the other should be rebased on top of latest main to remove the duplicate commit. I'm happy to do this housekeeping. I just mention it for clarity, and so that each PR can be reviewed independently, rather than forcing them to all be chained together. |
I'm going to try and look at your 2 pr's over the next week or 2. I want to avoid any breaking changes in the project as much as possible, especially since I just released a large set of breaking changes not too long ago. I do like performance increases and optimizations though, I really like them. I also need to figure out whats going on with the builds, they all started breaking. |
Coding style consistency is fine to keep, but when it becomes a blocker then sometimes it needs to be ignored. I'd like to see what you are thinking to reduce that cpu time, if you could send me a link to a commit outside of this pr so I could see what you mean then that would be great. |
Update: OK, I've reviewed all 5 PRs now, and none have breaking changes (at least that I can predict). I have a few more improvements I'd like to make, but it's somewhat difficult to keep them all independent at this point, so I'll focus on helping you review / land the existing items and then build from there. Let me know if you have any questions or concerns! |
OK, I've reviewed all 5 PRs now, and none have breaking changes (at least that I can predict). I'll respond back
Here's an example: 39d48eb That said today when I re-run with this change today I'm not seeing the slight benefit I saw yesterday over the existing pattern. Let me know your thoughts / concerns and I can dig in more and / or add additional benchmarks. |
I'm fine with that proposed change in that alternate commit you sent, putting the try/catch like that is just fine. |
In the provided serialization benchmark, there's an allocation of a
StringLookAheadBuffer
and aCharacterAnalyzer<T>
for each serialized entity:The CharacterAnalyzer allocations can be eliminated entirely by changing it from a
class
to areadonly struct
.StringLookAheadBuffer however has mutable state and thus can't become a struct without more significant refactoring. Instead, I chose to pool these objects. I tried to use the existing
ConcurrentObjectPool
. However, doing so showed a ~12% CPU regression on .NET Framework only (no CPU change on .NET Core). I instead updated the ConcurrentObjectPool to the newer ObjectPool that's part of Microsoft.Extensions.ObjectPool. I could bring that dependency in as a NuGet dependency, but because the package currently has no external dependencies, I chose to instead inline the implementation. I also upgraded the existingStringBuilderPool
to use the new object pool as well to avoid duplicate object pool implementations. Note that the Microsoft.Extensions.ObjectPool has different defaults than ConcurrentObjectPool did for the initial and max size of StringBuilder to pool. I picked the old values to prevent a behavior change.There's still a small CPU time regression on .NET Framework (~8%) in exchange for a comparable memory win on both .NET Framework and .NET Core. I can cut the size of the regression in half without impacting the memory savings by removing the RAII-style
BufferWrapper
struct and doing manualtry...finally
cleanup. I opt-ed not to in order to keep the coding style consistent, however I'm happy to make that change as well if desired.Before
After