From 5bb34e7b6ba8aebf7221ba00e78a77a72273dda1 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sun, 9 May 2021 00:34:11 +0300 Subject: [PATCH] Further reduce the runtime of parse_u64_digits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Here instead of figuring out the extents of the integer ahead of time we check for the spaces while we compute the number itself. This further reduces the runtime of the beforementioned case (see previous commit) to: 580.57 msec task-clock:u # 0.997 CPUs utilized 1,843,957,595 cycles:u # 3.176 GHz 5,901,570,558 instructions:u # 3.20 insn per cycle `perf report` still shows that the most of the time is spent parsing sysv archive names (which makes sense – its pretty much all the program does after all!). --- src/read/archive.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/read/archive.rs b/src/read/archive.rs index 97924bc6..2f507cb9 100644 --- a/src/read/archive.rs +++ b/src/read/archive.rs @@ -268,17 +268,19 @@ impl<'data> ArchiveMember<'data> { // Ignores bytes starting from the first space. fn parse_u64_digits(digits: &[u8], radix: u32) -> Option { - let len = memchr::memchr(b' ', digits).unwrap_or(digits.len()); - let digits = &digits[..len]; - if digits.is_empty() { + if let [b' ', ..] = digits { return None; } let mut result: u64 = 0; for &c in digits { - let x = (c as char).to_digit(radix)?; - result = result - .checked_mul(u64::from(radix))? - .checked_add(u64::from(x))?; + if c == b' ' { + return Some(result); + } else { + let x = (c as char).to_digit(radix)?; + result = result + .checked_mul(u64::from(radix))? + .checked_add(u64::from(x))?; + } } Some(result) } @@ -287,7 +289,7 @@ fn parse_sysv_extended_name<'data>(digits: &[u8], names: &'data [u8]) -> Result< let offset = parse_u64_digits(digits, 10).ok_or(())?; let offset = offset.try_into().map_err(|_| ())?; let name_data = names.get(offset..).ok_or(())?; - let name = match memchr::memchr2(b'/', 0, name_data) { + let name = match memchr::memchr2(b'/', b'\0', name_data) { Some(len) => &name_data[..len], None => name_data, }; @@ -304,7 +306,7 @@ fn parse_bsd_extended_name<'data, R: ReadRef<'data>>( let len = parse_u64_digits(digits, 10).ok_or(())?; *size = size.checked_sub(len).ok_or(())?; let name_data = data.read_bytes(offset, len)?; - let name = match memchr::memchr(0, name_data) { + let name = match memchr::memchr(b'\0', name_data) { Some(len) => &name_data[..len], None => name_data, };