Skip to content

Commit 700f13f

Browse files
committed
Replace original searchers with submodule
1 parent 8375986 commit 700f13f

File tree

21 files changed

+229
-453
lines changed

21 files changed

+229
-453
lines changed

.github/workflows/check.yml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ jobs:
44
cargo:
55
name: Cargo
66
runs-on: ubuntu-latest
7+
env:
8+
CXX: clang++
9+
LLVM_CONFIG_PATH: /usr/lib/llvm-9/bin/llvm-config
710
steps:
811
- uses: actions/checkout@v2
12+
with:
13+
submodules: true
914
- uses: actions-rs/toolchain@v1
1015
with:
1116
components: clippy, rustfmt
1217
default: true
13-
- run: cargo fmt -- --check
14-
- run: cargo build --all-targets --all-features
15-
- run: cargo clippy --all-targets --all-features -- -D warnings
16-
- run: cargo test --all-features
18+
- run: cargo fmt --all -- --check
19+
- run: cargo build --workspace --all-targets --all-features
20+
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings
21+
- run: cargo test --workspace --all-features

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
/target
1+
target/
22
Cargo.lock

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "sse4-strstr/src/sse4-strstr"]
2+
path = sse4-strstr/src/sse4-strstr
3+
url = https://github.com/WojciechMula/sse4-strstr.git

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ memchr = "2.3"
1818
[dev-dependencies]
1919
criterion = "0.3"
2020
memmem = "0.1"
21+
sse4-strstr = { path = "sse4-strstr" }
2122
twoway = "0.2"
2223

2324
[[bench]]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ A fast implementation of single-pattern substring search using SIMD acceleration
1010
## Example
1111

1212
```rust
13-
use sliceslice::x86::avx2::DynamicAvx2Searcher;
13+
use sliceslice::x86::DynamicAvx2Searcher;
1414

1515
fn main() {
1616
let searcher = unsafe { DynamicAvx2Searcher::new(b"ipsum".to_owned().into()) };

benches/i386.rs

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
#![allow(deprecated)]
2-
31
use criterion::{black_box, criterion_group, criterion_main, Criterion};
42
use memmem::{Searcher, TwoWaySearcher};
5-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
6-
use sliceslice::x86::avx2::{deprecated::*, *};
73
use std::{
84
fs::{self, File},
95
io::{BufRead, BufReader},
@@ -29,7 +25,7 @@ fn search_short_haystack(c: &mut Criterion) {
2925
});
3026
});
3127

32-
group.bench_function("TwoWaySearcher::search_in", |b| {
28+
group.bench_function("memmem::TwoWaySearcher::search_in", |b| {
3329
let searchers = needles
3430
.iter()
3531
.map(|needle| TwoWaySearcher::new(needle.as_bytes()))
@@ -56,24 +52,14 @@ fn search_short_haystack(c: &mut Criterion) {
5652

5753
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
5854
{
59-
group.bench_function("strstr_avx2_original", |b| {
60-
b.iter(|| {
61-
for (i, needle) in needles.iter().enumerate() {
62-
for haystack in &needles[i..] {
63-
black_box(unsafe {
64-
strstr_avx2_original(haystack.as_bytes(), needle.as_bytes())
65-
});
66-
}
67-
}
68-
});
69-
});
55+
use sliceslice::x86::DynamicAvx2Searcher;
7056

71-
group.bench_function("strstr_avx2_rust", |b| {
57+
group.bench_function("sse4_strstr::avx2_strstr_v2", |b| {
7258
b.iter(|| {
7359
for (i, needle) in needles.iter().enumerate() {
7460
for haystack in &needles[i..] {
7561
black_box(unsafe {
76-
strstr_avx2_rust(haystack.as_bytes(), needle.as_bytes())
62+
sse4_strstr::avx2_strstr_v2(haystack.as_bytes(), needle.as_bytes())
7763
});
7864
}
7965
}
@@ -120,7 +106,7 @@ fn search_long_haystack(c: &mut Criterion) {
120106
});
121107
});
122108

123-
group.bench_function("TwoWaySearcher::search_in", |b| {
109+
group.bench_function("memmem::TwoWaySearcher::search_in", |b| {
124110
let searchers = needles
125111
.iter()
126112
.map(|needle| TwoWaySearcher::new(needle.as_bytes()))
@@ -143,24 +129,18 @@ fn search_long_haystack(c: &mut Criterion) {
143129

144130
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
145131
{
146-
group.bench_function("strstr_avx2_original", |b| {
132+
use sliceslice::x86::DynamicAvx2Searcher;
133+
134+
group.bench_function("sse4_strstr::avx2_strstr_v2", |b| {
147135
b.iter(|| {
148136
for needle in &needles {
149137
black_box(unsafe {
150-
strstr_avx2_original(haystack.as_bytes(), needle.as_bytes())
138+
sse4_strstr::avx2_strstr_v2(haystack.as_bytes(), needle.as_bytes())
151139
});
152140
}
153141
});
154142
});
155143

156-
group.bench_function("strstr_avx2_rust", |b| {
157-
b.iter(|| {
158-
for needle in &needles {
159-
black_box(unsafe { strstr_avx2_rust(haystack.as_bytes(), needle.as_bytes()) });
160-
}
161-
});
162-
});
163-
164144
group.bench_function("DynamicAvx2Searcher::search_in", |b| {
165145
let searchers = needles
166146
.iter()

benches/random.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
#![allow(deprecated)]
2-
31
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
42
use memmem::{Searcher, TwoWaySearcher};
5-
use sliceslice::x86::avx2::{deprecated::*, *};
63

74
fn search(c: &mut Criterion) {
85
let haystack = include_str!("../data/haystack");
@@ -30,7 +27,7 @@ fn search(c: &mut Criterion) {
3027
let needle = needle.as_bytes();
3128

3229
group.bench_with_input(
33-
BenchmarkId::new("TwoWaySearcher::search_in", parameter),
30+
BenchmarkId::new("memmem::TwoWaySearcher::search_in", parameter),
3431
&size,
3532
|b, _| {
3633
let searcher = TwoWaySearcher::new(needle);
@@ -48,19 +45,15 @@ fn search(c: &mut Criterion) {
4845

4946
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
5047
{
51-
group.bench_with_input(
52-
BenchmarkId::new("strstr_avx2_original", parameter),
53-
&size,
54-
|b, _| {
55-
b.iter(|| black_box(unsafe { strstr_avx2_original(haystack, needle) }));
56-
},
57-
);
48+
use sliceslice::x86::DynamicAvx2Searcher;
5849

5950
group.bench_with_input(
60-
BenchmarkId::new("strstr_avx2_rust", parameter),
51+
BenchmarkId::new("sse4_strstr::avx2_strstr_v2", parameter),
6152
&size,
6253
|b, _| {
63-
b.iter(|| black_box(unsafe { strstr_avx2_rust(haystack, needle) }));
54+
b.iter(|| {
55+
black_box(unsafe { sse4_strstr::avx2_strstr_v2(haystack, needle) })
56+
});
6457
},
6558
);
6659

src/lib.rs

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! # Example
88
//!
99
//! ```
10-
//! use sliceslice::x86::avx2::DynamicAvx2Searcher;
10+
//! use sliceslice::x86::DynamicAvx2Searcher;
1111
//!
1212
//! let searcher = unsafe { DynamicAvx2Searcher::new(b"ipsum".to_owned().into()) };
1313
//!
@@ -19,15 +19,77 @@
1919
//! searcher.search_in(b"foo bar baz qux quux quuz corge grault garply waldo fred")
2020
//! });
2121
22-
#![allow(deprecated)]
2322
#![warn(missing_docs)]
2423

25-
/// Substring search implementations using the `memchr` function.
26-
pub mod memchr;
27-
2824
/// Substring search implementations using x86 architecture features.
2925
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
3026
pub mod x86;
3127

3228
mod bits;
3329
mod memcmp;
30+
31+
use memchr::memchr;
32+
33+
/// Single-byte searcher using `memchr` for faster matching.
34+
pub struct MemchrSearcher(u8);
35+
36+
impl MemchrSearcher {
37+
/// Creates a new searcher for `needle`.
38+
pub fn new(needle: u8) -> Self {
39+
Self(needle)
40+
}
41+
42+
/// Inlined version of `search_in` for hot call sites.
43+
#[inline]
44+
pub fn inlined_search_in(&self, haystack: &[u8]) -> bool {
45+
if haystack.is_empty() {
46+
return false;
47+
}
48+
49+
memchr(self.0, haystack).is_some()
50+
}
51+
52+
/// Performs a substring search for the `needle` within `haystack`.
53+
pub fn search_in(&self, haystack: &[u8]) -> bool {
54+
self.inlined_search_in(haystack)
55+
}
56+
}
57+
58+
#[cfg(test)]
59+
mod tests {
60+
use super::MemchrSearcher;
61+
62+
fn memchr_search(haystack: &[u8], needle: &[u8]) -> bool {
63+
MemchrSearcher::new(needle[0]).search_in(haystack)
64+
}
65+
66+
#[test]
67+
fn memchr_search_same() {
68+
assert!(memchr_search(b"f", b"f"));
69+
}
70+
71+
#[test]
72+
fn memchr_search_different() {
73+
assert!(!memchr_search(b"foo", b"b"));
74+
}
75+
76+
#[test]
77+
fn memchr_search_prefix() {
78+
assert!(memchr_search(b"foobar", b"f"));
79+
}
80+
81+
#[test]
82+
fn memchr_search_suffix() {
83+
assert!(memchr_search(b"foobar", b"r"));
84+
}
85+
86+
#[test]
87+
fn memchr_search_mutiple() {
88+
assert!(memchr_search(b"foobarfoo", b"o"));
89+
}
90+
91+
#[test]
92+
fn memchr_search_middle() {
93+
assert!(memchr_search(b"foobarfoo", b"b"));
94+
}
95+
}

src/memchr.rs

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)