diff options
| author | okaneco <47607823+okaneco@users.noreply.github.com> | 2024-09-23 00:10:18 -0400 |
|---|---|---|
| committer | okaneco <47607823+okaneco@users.noreply.github.com> | 2024-11-05 22:34:24 -0500 |
| commit | d7d67ad14b7c69325a3377bea83b9919398f9588 (patch) | |
| tree | dbdbad69446da475882ab2faa88bf7acefd17241 | |
| parent | 4a91ff6bb5f36a94d8ebebd9cad1f5f831abbe7a (diff) | |
| download | rust-d7d67ad14b7c69325a3377bea83b9919398f9588.tar.gz rust-d7d67ad14b7c69325a3377bea83b9919398f9588.zip | |
Add new implementation benchmark
Add LONG benchmarks for more comparison between the methods
| -rw-r--r-- | library/core/benches/ascii/is_ascii.rs | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/library/core/benches/ascii/is_ascii.rs b/library/core/benches/ascii/is_ascii.rs index 4b2920c5eb4..417d3e0fcbf 100644 --- a/library/core/benches/ascii/is_ascii.rs +++ b/library/core/benches/ascii/is_ascii.rs @@ -10,9 +10,12 @@ macro_rules! benches { // Ensure we benchmark cases where the functions are called with strings // that are not perfectly aligned or have a length which is not a // multiple of size_of::<usize>() (or both) - benches!(mod unaligned_head MEDIUM[1..] $($name $arg $body)+); - benches!(mod unaligned_tail MEDIUM[..(MEDIUM.len() - 1)] $($name $arg $body)+); - benches!(mod unaligned_both MEDIUM[1..(MEDIUM.len() - 1)] $($name $arg $body)+); + benches!(mod unaligned_head_medium MEDIUM[1..] $($name $arg $body)+); + benches!(mod unaligned_tail_medium MEDIUM[..(MEDIUM.len() - 1)] $($name $arg $body)+); + benches!(mod unaligned_both_medium MEDIUM[1..(MEDIUM.len() - 1)] $($name $arg $body)+); + benches!(mod unaligned_head_long LONG[1..] $($name $arg $body)+); + benches!(mod unaligned_tail_long LONG[..(LONG.len() - 1)] $($name $arg $body)+); + benches!(mod unaligned_both_long LONG[1..(LONG.len() - 1)] $($name $arg $body)+); }; (mod $mod_name: ident $input: ident [$range: expr] $($name: ident $arg: ident $body: block)+) => { @@ -49,6 +52,42 @@ benches! { fn case03_align_to_unrolled(bytes: &[u8]) { is_ascii_align_to_unrolled(bytes) } + + fn case04_while_loop(bytes: &[u8]) { + // Constant chosen to enable `pmovmskb` instruction on x86-64 + const N: usize = 32; + + let mut i = 0; + + while i + N <= bytes.len() { + let chunk_end = i + N; + + // Get LLVM to produce a `pmovmskb` instruction on x86-64 which + // creates a mask from the most significant bit of each byte. + // ASCII bytes are less than 128 (0x80), so their most significant + // bit is unset. Thus, detecting non-ASCII bytes can be done in one + // instruction. + let mut count = 0; + while i < chunk_end { + count += (bytes[i] <= 127) as u8; + i += 1; + } + + // All bytes should be <= 127 so count is equal to chunk size. + if count != N as u8 { + return false; + } + } + + // Process the remaining `bytes.len() % N` bytes. + let mut is_ascii = true; + while i < bytes.len() { + is_ascii &= bytes[i] <= 127; + i += 1; + } + + is_ascii + } } // These are separate since it's easier to debug errors if they don't go through |
