Skip to content

Commit dcbd5f5

Browse files
committed
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)
2 parents d35d972 + 3358a41 commit dcbd5f5

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

library/core/benches/fmt.rs

+11
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ fn write_str_macro_debug(bh: &mut Bencher) {
109109
});
110110
}
111111

112+
#[bench]
113+
fn write_str_macro_debug_ascii(bh: &mut Bencher) {
114+
bh.iter(|| {
115+
let mut mem = String::new();
116+
let wr = &mut mem as &mut dyn fmt::Write;
117+
for _ in 0..1000 {
118+
write!(wr, "{:?}", "Hello, World!").unwrap();
119+
}
120+
});
121+
}
122+
112123
#[bench]
113124
fn write_u128_max(bh: &mut Bencher) {
114125
bh.iter(|| {

library/core/src/unicode/printable.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def main():
170170
normal1 = compress_normal(normal1)
171171

172172
print("""\
173-
// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
173+
// NOTE: The following code was generated by "library/core/src/unicode/printable.py",
174174
// do not edit directly!
175175
176176
fn check(x: u16, singletonuppers: &[(u8, u8)], singletonlowers: &[u8], normal: &[u8]) -> bool {
@@ -211,7 +211,14 @@ def main():
211211
pub(crate) fn is_printable(x: char) -> bool {
212212
let x = x as u32;
213213
let lower = x as u16;
214-
if x < 0x10000 {
214+
215+
if x < 32 {
216+
// ASCII fast path
217+
false
218+
} else if x < 127 {
219+
// ASCII fast path
220+
true
221+
} else if x < 0x10000 {
215222
check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
216223
} else if x < 0x20000 {
217224
check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)

library/core/src/unicode/printable.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// NOTE: The following code was generated by "src/libcore/unicode/printable.py",
1+
// NOTE: The following code was generated by "library/core/src/unicode/printable.py",
22
// do not edit directly!
33

44
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: &
3939
pub(crate) fn is_printable(x: char) -> bool {
4040
let x = x as u32;
4141
let lower = x as u16;
42-
if x < 0x10000 {
42+
43+
if x < 32 {
44+
// ASCII fast path
45+
false
46+
} else if x < 127 {
47+
// ASCII fast path
48+
true
49+
} else if x < 0x10000 {
4350
check(lower, SINGLETONS0U, SINGLETONS0L, NORMAL0)
4451
} else if x < 0x20000 {
4552
check(lower, SINGLETONS1U, SINGLETONS1L, NORMAL1)

0 commit comments

Comments
 (0)