drain_inverse improve performance

master
Avril 4 years ago
parent 6b3b117a6f
commit f996d34bdf
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -25,25 +25,62 @@ pub trait FindSliceBounds
pub trait SliceInPlace pub trait SliceInPlace
{ {
fn slice_in_place(&mut self, slice: Range<usize>); #[deprecated = "Slow. Use `drain_inverse`"]
#[inline]
fn slice_in_place<R: std::ops::RangeBounds<usize>>(&mut self, slice: R)
{
self.drain_inverse(slice);
}
fn drain_inverse<R: std::ops::RangeBounds<usize>>(&mut self, slice: R);
} }
impl SliceInPlace for String impl SliceInPlace for String
{ {
fn slice_in_place(&mut self, slice: Range<usize>) { fn slice_in_place<R: std::ops::RangeBounds<usize>>(&mut self, slice: R) {
let mut i=0; let mut i=0;
self.retain(|_| (slice.contains(&i), i+=1).0); self.retain(|_| (slice.contains(&i), i+=1).0);
} }
fn drain_inverse<R: std::ops::RangeBounds<usize>>(&mut self, slice: R)
{
use std::ops::Bound;
match slice.end_bound() {
Bound::Excluded(&ex) => drop(self.drain(ex..)),
Bound::Included(&inc) => drop(self.drain(inc+1..)),
_ => (),
};
match slice.start_bound() {
Bound::Included(&ex) => drop(self.drain(..ex)),
Bound::Excluded(&ex) => drop(..ex+1),
_ => ()
};
}
} }
impl<T> SliceInPlace for Vec<T> impl<T> SliceInPlace for Vec<T>
{ {
fn slice_in_place(&mut self, slice: Range<usize>) { fn slice_in_place<R: std::ops::RangeBounds<usize>>(&mut self, slice: R) {
let mut i=0; let mut i=0;
self.retain(|_| (slice.contains(&i), i+=1).0); self.retain(|_| (slice.contains(&i), i+=1).0);
} }
fn drain_inverse<R: std::ops::RangeBounds<usize>>(&mut self, slice: R)
{
use std::ops::Bound;
match slice.end_bound() {
Bound::Excluded(&ex) => drop(self.drain(ex..)),
Bound::Included(&inc) => drop(self.drain(inc+1..)),
_ => (),
};
match slice.start_bound() {
Bound::Included(&ex) => drop(self.drain(..ex)),
Bound::Excluded(&ex) => drop(..ex+1),
_ => ()
};
}
} }
impl<T: ?Sized + AsRef<str>> FindSliceBounds for T impl<T: ?Sized + AsRef<str>> FindSliceBounds for T
{ {
type SliceType = str; type SliceType = str;
@ -72,6 +109,8 @@ impl<T: ?Sized + AsRef<str>> FindSliceBounds for T
#[cfg(test)] #[cfg(test)]
mod test_slice_in_place mod test_slice_in_place
{ {
use test::{Bencher, black_box};
use super::*; use super::*;
#[test] #[test]
fn slice_in_place_str() fn slice_in_place_str()
@ -85,6 +124,36 @@ mod test_slice_in_place
assert_eq!(&string[string.slice_bounds(string.trim())], string.trim()); assert_eq!(&string[string.slice_bounds(string.trim())], string.trim());
assert_eq!(&string[string.slice_bounds(string.trim())], "hello world"); assert_eq!(&string[string.slice_bounds(string.trim())], "hello world");
} }
#[bench]
fn bench_slice_in_place(b: &mut Bencher)
{
let mut string = String::from("hello ONE TWO world");
b.iter(|| {
black_box(string.slice_in_place(7..16));
string.push_str("ONE TWO");
});
}
#[bench]
fn bench_drain_inverse(b: &mut Bencher)
{
let mut string = String::from("hello ONE TWO world");
b.iter(|| {
black_box(string.drain_inverse(7..16));
string.push_str("ONE TWO");
});
}
#[test]
fn drain_inverse()
{
let mut string = String::from("123hello world5678");
string.drain_inverse(3..=13);
assert_eq!(&string[..], "hello world");
string.drain_inverse(6..);
assert_eq!(&string[..], "world");
}
} }

@ -274,7 +274,7 @@ impl KeyHeader
} }
buffer.slice_bounds(trimmed) buffer.slice_bounds(trimmed)
}; };
buffer.slice_in_place(bounds); buffer.drain_inverse(bounds);
if { if {
let bytes = buffer.as_bytes(); let bytes = buffer.as_bytes();

Loading…
Cancel
Save