-
Notifications
You must be signed in to change notification settings - Fork 8.5k
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
Perf: save text buffer size for frequent access #3351
Perf: save text buffer size for frequent access #3351
Conversation
dd10a15
to
ca02845
Compare
aa791b0
to
b2fe70d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems safe to me. IIRC, we don't ever really resize a single TextBuffer, we usually just make a new one, and copy the contents over. So this seems like it'll work to me.
In fact, we probably don't even need _UpdateSize at all, since we've only ever got a rectangular buffer, every row should be the same width. Thoughts 🤔?
As much as I'm usually in favor of having less redundant copies of information laying around, this seems like a scenario where caching this information would be beneficial. Plus, I won't have to drill 3 layers past the buffer in the debugger anymore to check it's size :P
The static analysis is killing me. This |
8d2a3a2
to
c6f12ff
Compare
Well the good thing is that, this insane |
c6f12ff
to
e7b1cc5
Compare
Is there a way to cast function pointer with auto moveFunc = &_moveByDocument;
if (unit == TextUnit::TextUnit_Character)
{
moveFunc = &_moveByCharacter;
}
else if (unit <= TextUnit::TextUnit_Line)
{
moveFunc = &_moveByLine;
} Here |
e7b1cc5
to
b890846
Compare
b890846
to
ef7df97
Compare
@@ -579,7 +579,7 @@ IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit, | |||
_outputRowConversions(); | |||
#endif | |||
|
|||
auto moveFunc = &_moveByDocument; | |||
std::pair<unsigned, unsigned> (*moveFunc)(gsl::not_null<IUiaData*>, int, MoveState, gsl::not_null<int*>) = &_moveByDocument; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK I have no idea it would end up like this. If anyone has better way to do this, please enlighten me.
We used to have 12 copies of the buffer size that got out of sync. I very intentionally didn't store it in a property here, so I'm not totally happy with this PR overall. @skyline75489, do you have a performance test that shows this change is actually resulting in a performance improvement? A WPR trace? Or is this "by inspection" only? @zadjii-msft, if it's hard for you to see it in the debugger, we should file an issue to add a .natvis rule for it, not store another copy. I would like this PR blocked until I see actual proof of the performance gain. We have been burned SO HARD in the past by storing the size somewhere that isn't the inherent structural size that I really do NOT want to do this unless justified fully. |
@miniksa The Speaking of profiling, my previous PRs are also based on profiling result. Recently #3262 is filed. Just like this PR, it aims to reduce unnecessary vector access. For safety reason, vectors and deques are used across the entire codebase. But the random access performance is not good enough, especially under very intensive calls. The trade-off, though, is still reasonable to me. I'd also prefer more PRs like #3262 that reduces the access, rather than reduing the usage of stl containers. |
Can you show me the profiling results here? Like the hot frames off the stack or whatnot? Or attach the ETW traces? If it's 4% penalty, then maybe we should do this and just make sure it's well-guarded inside the
If you are seeing massive random access problems, please show me the proof and let me know so we can consider. |
Also, it was my understanding that the .size() property of the STL structures didn't require calculation.... it should just be there statically as a part of the structure overhead. So I'm somewhat surprised there's a penalty. |
@miniksa There you go, the screenshot.
Come to think about it, perhaps you are right. It could be that the super intensive access that causes the CPU usage. For example in #3262 the My guess it that, |
I'm using the Debug build for profiling. What I did was simply just If with Release build the usage drops to a noise level then maybe it's not worth the effort to go through this patching thing. |
Oh heck yeah, the STL is absolutely loaded with runtime checks in debug builds. I wouldn't use debug builds for any type of perf-sensitive measurements, especially where the STL is involved 😄 |
@DHowett-MSFT That's a relief. The |
So @skyline75489, is there still a dramatic difference between the before-your-fix and after-your-fix with a Release build? Also, sorry about the |
@miniksa The performance differences doses drop to a noise level with a Release build. I’m gonna close this for now. I’m just really glad the noexcept things will not be merged. |
Yes, we need to revisit this. This is another of the things I saw while working on #6483 on Friday. It's harder to see because it happens in multiple places and I'm really not sure why it's such a pig at pulling these out of that function, but we should bring this back and get it gone. |
It's been too long since this PR is born. I can not find my local branch anymore. I'm still fighting my techinical issues with my PC and I'm not able to offer help for now. (sorry about that 😢 ) |
No problem, I'll make my own version. Thanks! |
Summary of the Pull Request
Save buffer size as a property. Update it when necessary.
References
PR Checklist
Detailed Description of the Pull Request / Additional comments
The
GetSize
in text buffer is called intensively across the entire code base. The buffer size is frequently accessed but seldom modified. This is an attempt to make use of that.Validation Steps Performed