Auto merge of #97526 - Nilstrieb:unicode-is-printable-fastpath, r=joshtriplett

Add unicode fast path to `is_printable`

Before, it would enter the full expensive check even for normal ascii characters. Now, it skips the check for the ascii characters in `32..127`. This range was checked manually from the current behavior.

I ran the `tracing` test suite in miri, and it was really slow. I looked at a profile, and miri spent most of the time in `core::char::methods::escape_debug_ext`, where half of that was dominated by `core::unicode::printable::is_printable`. So I optimized it here.

The tracing profile:
![The tracing profile](https://user-images.githubusercontent.com/48135649/170883650-23876e7b-3fd1-4e8b-9001-47672e06d914.svg)
This commit is contained in:
bors 2022-05-31 09:34:00 +00:00
commit dcbd5f5134
3 changed files with 29 additions and 4 deletions

View File

@ -109,6 +109,17 @@ fn write_str_macro_debug(bh: &mut Bencher) {
});
}
#[bench]
fn write_str_macro_debug_ascii(bh: &mut Bencher) {
bh.iter(|| {
let mut mem = String::new();
let wr = &mut mem as &mut dyn fmt::Write;
for _ in 0..1000 {
write!(wr, "{:?}", "Hello, World!").unwrap();
}
});
}
#[bench]
fn write_u128_max(bh: &mut Bencher) {
bh.iter(|| {

View File

@ -170,7 +170,7 @@ def main():
normal1 = compress_normal(normal1)
print("""\
// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
// NOTE: The following code was generated by "library/core/src/unicode/printable.py",
// do not edit directly!
fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool {
@ -211,7 +211,14 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &
pub(crate) fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
if x < 32 {
// ASCII fast path
false
} else if x < 127 {
// ASCII fast path
true
} else if x < 0x10000 {
check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
} else if x < 0x20000 {
check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)

View File

@ -1,4 +1,4 @@
// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
// NOTE: The following code was generated by "library/core/src/unicode/printable.py",
// do not edit directly!
fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool {
@ -39,7 +39,14 @@ fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &
pub(crate) fn is_printable(x: char) -> bool {
let x = x as u32;
let lower = x as u16;
if x < 0x10000 {
if x < 32 {
// ASCII fast path
false
} else if x < 127 {
// ASCII fast path
true
} else if x < 0x10000 {
check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
} else if x < 0x20000 {
check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)