Skip to content

Commit 41debc3

Browse files
committed
Try to optimise char patterns
1 parent 386b0b9 commit 41debc3

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

src/libcollections/benches/str.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -195,30 +195,34 @@ fn bench_contains_equal(b: &mut Bencher) {
195195
})
196196
}
197197

198+
198199
macro_rules! make_test_inner {
199-
($s:ident, $code:expr, $name:ident, $str:expr) => {
200+
($s:ident, $code:expr, $name:ident, $str:expr, $iters:expr) => {
200201
#[bench]
201202
fn $name(bencher: &mut Bencher) {
202203
let mut $s = $str;
203204
black_box(&mut $s);
204-
bencher.iter(|| $code);
205+
bencher.iter(|| for _ in 0..$iters { black_box($code); });
205206
}
206207
}
207208
}
208209

209210
macro_rules! make_test {
210211
($name:ident, $s:ident, $code:expr) => {
212+
make_test!($name, $s, $code, 1);
213+
};
214+
($name:ident, $s:ident, $code:expr, $iters:expr) => {
211215
mod $name {
212216
use test::Bencher;
213217
use test::black_box;
214218

215219
// Short strings: 65 bytes each
216220
make_test_inner!($s, $code, short_ascii,
217-
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
221+
"Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!", $iters);
218222
make_test_inner!($s, $code, short_mixed,
219-
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
223+
"ศไทย中华Việt Nam; Mary had a little lamb, Little lam!", $iters);
220224
make_test_inner!($s, $code, short_pile_of_poo,
221-
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
225+
"💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!", $iters);
222226
make_test_inner!($s, $code, long_lorem_ipsum,"\
223227
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
224228
ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
@@ -253,7 +257,7 @@ Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas
253257
feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
254258
vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
255259
leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
256-
malesuada sollicitudin quam eu fermentum!");
260+
malesuada sollicitudin quam eu fermentum!", $iters);
257261
}
258262
}
259263
}
@@ -288,6 +292,13 @@ make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
288292
make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
289293
make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
290294

295+
make_test!(starts_with_ascii_char, s, s.starts_with('/'), 1024);
296+
make_test!(ends_with_ascii_char, s, s.ends_with('/'), 1024);
297+
make_test!(starts_with_unichar, s, s.starts_with('\u{1F4A4}'), 1024);
298+
make_test!(ends_with_unichar, s, s.ends_with('\u{1F4A4}'), 1024);
299+
make_test!(starts_with_str, s, s.starts_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
300+
make_test!(ends_with_str, s, s.ends_with("💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩"), 1024);
301+
291302
make_test!(split_space_char, s, s.split(' ').count());
292303
make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
293304

src/libcollections/str.rs

+14
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,7 @@ impl str {
813813
/// assert!(!bananas.contains("apples"));
814814
/// ```
815815
#[stable(feature = "rust1", since = "1.0.0")]
816+
#[inline]
816817
pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
817818
core_str::StrExt::contains(self, pat)
818819
}
@@ -900,6 +901,7 @@ impl str {
900901
/// assert_eq!(s.find(x), None);
901902
/// ```
902903
#[stable(feature = "rust1", since = "1.0.0")]
904+
#[inline]
903905
pub fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
904906
core_str::StrExt::find(self, pat)
905907
}
@@ -944,6 +946,7 @@ impl str {
944946
/// assert_eq!(s.rfind(x), None);
945947
/// ```
946948
#[stable(feature = "rust1", since = "1.0.0")]
949+
#[inline]
947950
pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
948951
where P::Searcher: ReverseSearcher<'a>
949952
{
@@ -1057,6 +1060,7 @@ impl str {
10571060
///
10581061
/// [`split_whitespace`]: #method.split_whitespace
10591062
#[stable(feature = "rust1", since = "1.0.0")]
1063+
#[inline]
10601064
pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
10611065
core_str::StrExt::split(self, pat)
10621066
}
@@ -1106,6 +1110,7 @@ impl str {
11061110
/// assert_eq!(v, ["ghi", "def", "abc"]);
11071111
/// ```
11081112
#[stable(feature = "rust1", since = "1.0.0")]
1113+
#[inline]
11091114
pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
11101115
where P::Searcher: ReverseSearcher<'a>
11111116
{
@@ -1152,6 +1157,7 @@ impl str {
11521157
/// assert_eq!(v, ["A", "", "B", ""]);
11531158
/// ```
11541159
#[stable(feature = "rust1", since = "1.0.0")]
1160+
#[inline]
11551161
pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
11561162
core_str::StrExt::split_terminator(self, pat)
11571163
}
@@ -1195,6 +1201,7 @@ impl str {
11951201
/// assert_eq!(v, ["", "B", "", "A"]);
11961202
/// ```
11971203
#[stable(feature = "rust1", since = "1.0.0")]
1204+
#[inline]
11981205
pub fn rsplit_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplitTerminator<'a, P>
11991206
where P::Searcher: ReverseSearcher<'a>
12001207
{
@@ -1247,6 +1254,7 @@ impl str {
12471254
/// assert_eq!(v, ["abc", "defXghi"]);
12481255
/// ```
12491256
#[stable(feature = "rust1", since = "1.0.0")]
1257+
#[inline]
12501258
pub fn splitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> SplitN<'a, P> {
12511259
core_str::StrExt::splitn(self, n, pat)
12521260
}
@@ -1294,6 +1302,7 @@ impl str {
12941302
/// assert_eq!(v, ["ghi", "abc1def"]);
12951303
/// ```
12961304
#[stable(feature = "rust1", since = "1.0.0")]
1305+
#[inline]
12971306
pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, n: usize, pat: P) -> RSplitN<'a, P>
12981307
where P::Searcher: ReverseSearcher<'a>
12991308
{
@@ -1334,6 +1343,7 @@ impl str {
13341343
/// assert_eq!(v, ["1", "2", "3"]);
13351344
/// ```
13361345
#[stable(feature = "str_matches", since = "1.2.0")]
1346+
#[inline]
13371347
pub fn matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> Matches<'a, P> {
13381348
core_str::StrExt::matches(self, pat)
13391349
}
@@ -1370,6 +1380,7 @@ impl str {
13701380
/// assert_eq!(v, ["3", "2", "1"]);
13711381
/// ```
13721382
#[stable(feature = "str_matches", since = "1.2.0")]
1383+
#[inline]
13731384
pub fn rmatches<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatches<'a, P>
13741385
where P::Searcher: ReverseSearcher<'a>
13751386
{
@@ -1415,6 +1426,7 @@ impl str {
14151426
/// assert_eq!(v, [(0, "aba")]); // only the first `aba`
14161427
/// ```
14171428
#[stable(feature = "str_match_indices", since = "1.5.0")]
1429+
#[inline]
14181430
pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
14191431
core_str::StrExt::match_indices(self, pat)
14201432
}
@@ -1457,6 +1469,7 @@ impl str {
14571469
/// assert_eq!(v, [(2, "aba")]); // only the last `aba`
14581470
/// ```
14591471
#[stable(feature = "str_match_indices", since = "1.5.0")]
1472+
#[inline]
14601473
pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
14611474
where P::Searcher: ReverseSearcher<'a>
14621475
{
@@ -1737,6 +1750,7 @@ impl str {
17371750
/// assert_eq!(s, s.replace("cookie monster", "little lamb"));
17381751
/// ```
17391752
#[stable(feature = "rust1", since = "1.0.0")]
1753+
#[inline]
17401754
pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
17411755
let mut result = String::new();
17421756
let mut last_end = 0;

src/libcore/str/pattern.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,33 @@ impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
429429

430430
/// Searches for chars that are equal to a given char
431431
impl<'a> Pattern<'a> for char {
432-
pattern_methods!(CharSearcher<'a>, CharEqPattern, CharSearcher);
432+
type Searcher = CharSearcher<'a>;
433+
434+
#[inline]
435+
fn into_searcher(self, haystack: &'a str) -> Self::Searcher {
436+
CharSearcher(CharEqPattern(self).into_searcher(haystack))
437+
}
438+
439+
#[inline]
440+
fn is_contained_in(self, haystack: &'a str) -> bool {
441+
if (self as u32) < 128 {
442+
haystack.as_bytes().contains(&(self as u8))
443+
} else {
444+
let mut buffer = [0u8; 4];
445+
self.encode_utf8(&mut buffer).is_contained_in(haystack)
446+
}
447+
}
448+
449+
#[inline]
450+
fn is_prefix_of(self, haystack: &'a str) -> bool {
451+
CharEqPattern(self).is_prefix_of(haystack)
452+
}
453+
454+
#[inline]
455+
fn is_suffix_of(self, haystack: &'a str) -> bool where Self::Searcher: ReverseSearcher<'a>
456+
{
457+
CharEqPattern(self).is_suffix_of(haystack)
458+
}
433459
}
434460

435461
/////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)