From 7f6e080120fe3c2fd067a5b8d5df04b45ef78b09 Mon Sep 17 00:00:00 2001 From: The8472 Date: Fri, 5 Nov 2021 01:08:19 +0100 Subject: [PATCH] add fast path on Path::eq for exact equality --- library/std/src/path.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index aca3a42f20ad1..33225692d1771 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -979,6 +979,25 @@ impl FusedIterator for Components<'_> {} impl<'a> cmp::PartialEq for Components<'a> { #[inline] fn eq(&self, other: &Components<'a>) -> bool { + let Components { path: _, front: _, back: _, has_physical_root: _, prefix: _ } = self; + + // Fast path for exact matches, e.g. for hashmap lookups. + // Don't explicitly compare the prefix or has_physical_root fields since they'll + // either be covered by the `path` buffer or are only relevant for `prefix_verbatim()`. + if self.path.len() == other.path.len() + && self.front == other.front + && self.back == State::Body + && other.back == State::Body + && self.prefix_verbatim() == other.prefix_verbatim() + { + // possible future improvement: this could bail out earlier if there were a + // reverse memcmp/bcmp comparing back to front + if self.path == other.path { + return true; + } + } + + // compare back to front since absolute paths often share long prefixes Iterator::eq(self.clone().rev(), other.clone().rev()) } } @@ -1013,7 +1032,7 @@ fn compare_components(mut left: Components<'_>, mut right: Components<'_>) -> cm // The fast path isn't taken for paths with a PrefixComponent to avoid backtracking into // the middle of one if left.prefix.is_none() && right.prefix.is_none() && left.front == right.front { - // this might benefit from a [u8]::first_mismatch simd implementation, if it existed + // possible future improvement: a [u8]::first_mismatch simd implementation let first_difference = match left.path.iter().zip(right.path.iter()).position(|(&a, &b)| a != b) { None if left.path.len() == right.path.len() => return cmp::Ordering::Equal,