Specialize equality for [T] and comparison for [u8]
Where T is a type that can be compared for equality bytewise, we can use memcmp. We can also use memcmp for PartialOrd, Ord for [u8] and by extension &str. This is an improvement for example for the comparison [u8] == [u8] that used to emit a loop that compared the slices byte by byte. One worry here could be that this introduces function calls to memcmp in contexts where it should really inline the comparison or even optimize it out, but llvm takes care of recognizing memcmp specifically.
This commit is contained in:
parent
a09f386e8d
commit
5d56e1daed
3 changed files with 147 additions and 46 deletions
|
@ -1150,16 +1150,7 @@ Section: Comparing strings
|
|||
#[lang = "str_eq"]
|
||||
#[inline]
|
||||
fn eq_slice(a: &str, b: &str) -> bool {
|
||||
a.len() == b.len() && unsafe { cmp_slice(a, b, a.len()) == 0 }
|
||||
}
|
||||
|
||||
/// Bytewise slice comparison.
|
||||
/// NOTE: This uses the system's memcmp, which is currently dramatically
|
||||
/// faster than comparing each byte in a loop.
|
||||
#[inline]
|
||||
unsafe fn cmp_slice(a: &str, b: &str, len: usize) -> i32 {
|
||||
extern { fn memcmp(s1: *const i8, s2: *const i8, n: usize) -> i32; }
|
||||
memcmp(a.as_ptr() as *const i8, b.as_ptr() as *const i8, len)
|
||||
a.as_bytes() == b.as_bytes()
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1328,8 +1319,7 @@ Section: Trait implementations
|
|||
*/
|
||||
|
||||
mod traits {
|
||||
use cmp::{self, Ordering, Ord, PartialEq, PartialOrd, Eq};
|
||||
use cmp::Ordering::{Less, Greater};
|
||||
use cmp::{Ord, Ordering, PartialEq, PartialOrd, Eq};
|
||||
use iter::Iterator;
|
||||
use option::Option;
|
||||
use option::Option::Some;
|
||||
|
@ -1340,16 +1330,7 @@ mod traits {
|
|||
impl Ord for str {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &str) -> Ordering {
|
||||
let cmp = unsafe {
|
||||
super::cmp_slice(self, other, cmp::min(self.len(), other.len()))
|
||||
};
|
||||
if cmp == 0 {
|
||||
self.len().cmp(&other.len())
|
||||
} else if cmp < 0 {
|
||||
Less
|
||||
} else {
|
||||
Greater
|
||||
}
|
||||
self.as_bytes().cmp(other.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue