about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-03-11 13:38:37 +0100
committerGitHub <noreply@github.com>2022-03-11 13:38:37 +0100
commitcdd6d39eccb687f20113893902eafd8ba81b4acf (patch)
tree93f2bb9412734f3c27a53e51c461ee9aba72cb3b
parentb711d17c374d7538c8f716cbeaf0fe8c6f7cd691 (diff)
parentc62ab422d06410772e364c61741376e10b39fff8 (diff)
downloadrust-cdd6d39eccb687f20113893902eafd8ba81b4acf.tar.gz
rust-cdd6d39eccb687f20113893902eafd8ba81b4acf.zip
Rollup merge of #94776 - martingms:optimize-escape-default, r=nnethercote
Optimize ascii::escape_default

`ascii::escape_default` showed up as a hot function when compiling `deunicode-1.3.1` in `@nnethercote's` [analysis](https://hackmd.io/mxdn4U58Su-UQXwzOHpHag) of `@lqd's` [rustc-benchmarking-data](https://github.com/lqd/rustc-benchmarking-data).
After taking a look at the generated assembly it looked like a LUT-based approach could be faster for `hexify()`-ing ascii characters, so that's what this PR implements

The patch looks like it provides about a 1-2% improvement in instructions for that particular crate. This should definitely be verified with a perf run as I'm still getting used to the `rustc-perf` tooling and might easily have made an error!
-rw-r--r--library/core/src/ascii.rs14
1 files changed, 6 insertions, 8 deletions
diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs
index 532208e41af..8a4cb78cc7f 100644
--- a/library/core/src/ascii.rs
+++ b/library/core/src/ascii.rs
@@ -98,22 +98,20 @@ pub fn escape_default(c: u8) -> EscapeDefault {
         b'\'' => ([b'\\', b'\'', 0, 0], 2),
         b'"' => ([b'\\', b'"', 0, 0], 2),
         b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
-        _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
+        _ => {
+            let hex_digits: &[u8; 16] = b"0123456789abcdef";
+            ([b'\\', b'x', hex_digits[(c >> 4) as usize], hex_digits[(c & 0xf) as usize]], 4)
+        }
     };
 
     return EscapeDefault { range: 0..len, data };
-
-    fn hexify(b: u8) -> u8 {
-        match b {
-            0..=9 => b'0' + b,
-            _ => b'a' + b - 10,
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for EscapeDefault {
     type Item = u8;
+
+    #[inline]
     fn next(&mut self) -> Option<u8> {
         self.range.next().map(|i| self.data[i as usize])
     }