Skip to content

Commit

Permalink
Auto merge of #97526 - Nilstrieb:unicode-is-printable-fastpath, r=jos…
Browse files Browse the repository at this point in the history
…htriplett

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)
  • Loading branch information
bors committed May 31, 2022
2 parents d35d972 + 3358a41 commit dcbd5f5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 4 deletions.
11 changes: 11 additions & 0 deletions library/core/benches/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(|| {
Expand Down
11 changes: 9 additions & 2 deletions library/core/src/unicode/printable.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -211,7 +211,14 @@ def main():
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)
Expand Down
11 changes: 9 additions & 2 deletions library/core/src/unicode/printable.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit dcbd5f5

Please sign in to comment.