Skip to content
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: improve utf_char2cells() performance #27353

Merged
merged 2 commits into from Feb 7, 2024

Conversation

vanaigr
Copy link
Contributor

@vanaigr vanaigr commented Feb 5, 2024

utf_char2cells() calls utf_printable() twice (sometimes indirectly, through vim_isprintc()) for characters >= 128. The function can be refactored to call to it only once.

utf_printable() uses binary search on ranges of unprintable characters to determine if a given character is printable. Since there are only 9 ranges, and the first range contains only one character, binary search can be replaced with SSE2 SIMD comparisons that check 8 ranges at a time, and the first range is checked separately.
SSE2 is enabled by default in GCC, Clang and MSVC for x86-64.

I tested the function and it returns the same results for all 2^32 values.

Benchmarks:

I modified the benchmarks from #26813 to better reflect the performance difference and added a new benchmark that measures 3 byte utf-8 separately.

ascii 2 byte 3 byte random
before 14 85 194 170
after 13 83 172 154

src/nvim/mbyte.c Outdated Show resolved Hide resolved
@zeertzjq
Copy link
Member

zeertzjq commented Feb 6, 2024

You may also want to take #18690 into consideration.

@zeertzjq zeertzjq added performance issues reporting performance problems unicode 💩 (multibyte) unicode characters labels Feb 6, 2024
@vanaigr
Copy link
Contributor Author

vanaigr commented Feb 7, 2024

Should I make characters above 10FFFF unprintable?

@zeertzjq
Copy link
Member

zeertzjq commented Feb 7, 2024

Hmm, actually it's not hard to add that check later, so not really necessary.

@zeertzjq zeertzjq added ci:s390x Enable CI for s390x and removed ci:s390x Enable CI for s390x labels Feb 7, 2024
src/nvim/mbyte.c Outdated Show resolved Hide resolved
src/nvim/mbyte.c Outdated Show resolved Hide resolved
src/nvim/mbyte.c Outdated Show resolved Hide resolved
@zeertzjq zeertzjq merged commit cca8a78 into neovim:master Feb 7, 2024
24 checks passed
@marcelbeumer
Copy link

Thanks so much everyone!

@vanaigr vanaigr deleted the faster-char2cells branch March 29, 2024 21:13
glepnir pushed a commit to glepnir/neovim that referenced this pull request Mar 31, 2024
`utf_char2cells()` calls `utf_printable()` twice (sometimes indirectly,
through `vim_isprintc()`) for characters >= 128. The function can be
refactored to call to it only once.

`utf_printable()` uses binary search on ranges of unprintable characters
to determine if a given character is printable. Since there are only 9
ranges, and the first range contains only one character, binary search
can be replaced with SSE2 SIMD comparisons that check 8 ranges at a
time, and the first range is checked separately. SSE2 is enabled by
default in GCC, Clang and MSVC for x86-64.

Add 3-byte utf-8 to screenpos_spec benchmarks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance issues reporting performance problems unicode 💩 (multibyte) unicode characters
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants