-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
Prefer FMT_COMPILE for string formatting in VtRenderer #10426
Prefer FMT_COMPILE for string formatting in VtRenderer #10426
Conversation
@check-spelling-bot ReportUnrecognized words, please review:
Previously acknowledged words that are now absenthpcon serializers testnetv Tlg XpathTo accept these unrecognized words as correct (and remove the previously acknowledged and now absent words), run the following commands... in a clone of the [email protected]:skyline75489/terminal.git repository
✏️ Contributor please read thisBy default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
If the listed items are:
See the 🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉 🗜️ If you see a bunch of garbageIf it relates to a ... well-formed patternSee if there's a pattern that would match it. If not, try writing one and adding it to a Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines. Note that patterns can't match multiline strings. binary-ish stringPlease add a file path to the File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.
|
I like the idea because you're right, this is a pain point. But I thought that |
Dustin suggested FMT_COMPILE so I tried that. It’s still can be seen as more of a general purpose formatting method. comparing to the original code (10% CPU time), FMT_COMPLIE is faster(~5%), but not the fastest. This PR I believe is the fastest(< 2%), because it is the dirtiest and more specialized. |
One thing I learned while writing this PR is that even the construction of std::string is reasonably expensive when used very frequently. This is why (I believe) FMT_COMPILE is dragged behind in performance. In this PR I managed to do zero heap allocation & zero objection construction to minimize the memory footprint & CPU cycles. |
Can you try...
? This lets us format into a buffer. :P |
Thanks @DHowett for informing me of |
I'm marking this "ready for review". I have two lingering questions:
|
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.
_WriteFormattedString
takes a std::string
as its first argument.
While this doesn't allocate anything thanks to SSO, it feels weird to me that we do it that way when you can just... you know... pass the char pointer directly lol.
So if you feel like it, it would be nice if the first argument of _WriteFormattedString
was changed to _Printf_format_string_ STRSAFE_LPCSTR
IMO. (Just IMO! 😄)
@check-spelling-bot ReportUnrecognized words, please review:
Previously acknowledged words that are now absentADDB hpcon serializers testnetv Tlg XpathTo accept these unrecognized words as correct (and remove the previously acknowledged and now absent words), run the following commands... in a clone of the [email protected]:skyline75489/terminal.git repository
✏️ Contributor please read thisBy default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.
If the listed items are:
See the 🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉 🗜️ If you see a bunch of garbageIf it relates to a ... well-formed patternSee if there's a pattern that would match it. If not, try writing one and adding it to a Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines. Note that patterns can't match multiline strings. binary-ish stringPlease add a file path to the File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.
|
It would fit fmt's design a bit better, true. |
You know I was curious whether MSVC properly optimizes #include <string_view>
extern int foo(std::string_view);
int test() {
return foo("aaaaaaaa");
} This is GCC ( .LC0:
.string "aaaaaaaa"
test():
mov edi, 8
mov esi, OFFSET FLAT:.LC0
jmp foo(std::basic_string_view<char, std::char_traits<char> >) This is MSVC ( `string' DB 'aaaaaaaa', 00H ; `string'
$T1 = 32
$T2 = 32
int test(void) PROC ; test, COMDAT
$LN9:
sub rsp, 56 ; 00000038H
mov QWORD PTR $T2[rsp+8], 8
lea rax, OFFSET FLAT:`string'
mov QWORD PTR $T2[rsp], rax
lea rcx, QWORD PTR $T1[rsp]
movaps xmm0, XMMWORD PTR $T2[rsp]
movdqa XMMWORD PTR $T1[rsp], xmm0
call int foo(std::basic_string_view<char,std::char_traits<char> >) ; foo
add rsp, 56 ; 00000038H
ret 0
int test(void) ENDP ; test Why does MSVC allocate 56 bytes on the stack for, to call a function that takes two parameters as a struct. And am I seeing this correctly? |
Windows x64 calling convention passes structs by reference if they're larger than 8 bytes. 😑 But I just can't get over this in particular: movaps xmm0, XMMWORD PTR $T2[rsp]
movdqa XMMWORD PTR $T1[rsp], xmm0 The compiler copies 16 bytes from This bit of assembly is not generated if you pass the Edit: Yep, I benchmarked it and passing a |
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.
I'm impressed with how minimally-invasive the changes are for the impact it gives us. I'm just blocking over the stateMachine changes 😄 since they seem like they belong in #10471.
FYI @skyline75489: |
Oh yeah now that you mentioned it, there's slight binary size increase caused by this. I thin it's worth is, considering the performance boost. Hope it does not cause trouble regarding inbox requirement. |
@skyline75489 How are you measuring the binary size? I'm building Host.EXE and I'm seeing no size changes between main and your branch. In fact it's almost 1kB smaller, but that isn't really anything significant, when OpenConsole is 1.104MB. |
Huh, strange. I'm seeing main (1102 KB) and my branch (1107KB). Release x64 Build of |
Maybe you want to pull this branch again. I rebased master just minutes ago, |
Hello @DHowett! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
Thank you, @skyline75489! |
Thanks @mmozeiko for the original inspiration of this PR. I'm sorry that this does not give us 3X performance boost (as @jfhs This change should be shipped in the next version of Windows Terminal (OpenConsole). But unfortunately it won't be shipped soon in Windows itself (as in conhost), because of the shipping schedule of Windows is much more complicated. I don't like this, either. But I can live with it. And I'd like to point out that I am NOT part of the terminal dev team. I'm a MS employee but I work for Azure now. I'm just contributing to this project as an outside contributor since the year 2019 (we call it "moonlighting" inside MS). And I joined MS after that at the year 2020. Being inside MS gave me a better channel to talk to the members of the official dev team, and helped me establishing (dare I say) a nice friendship with them. I'd also like to point out that me being an outside contributor actually helps me creating PRs like this one, because being an official member means that you'll have all the OKRs, the managerial metrics, the milestones and everything. You can't really just do whatever you want with the project. That's why community contributors play a vital rule in the development process. I do believe the team welcome all kinds of contributions, because that's the idea of open source, right? I'm sure the team did not try convincing the higher management to open source this project, just to show what a group of good programmers they are (or did they? 👀) |
Kill `WriteFormattedString` and replace it with `fmt::format_to` to avoid expensive string operations in VtRenderer. This saves ~8% of the CPU time. Inspired by #10362 (comment) Co-authored-by: Leonard Hecker <[email protected]> (cherry picked from commit 4f0b57e)
🎉 Handy links: |
🎉 Handy links: |
Kill
WriteFormattedString
and replace it withfmt::format_to
to avoid expensive string operations in VtRenderer.This saves ~8% of the CPU time.
Inspired by #10362 (comment)
Co-authored-by: Leonard Hecker [email protected]