Skip to content

Commit

Permalink
Merge pull request #6 from CleverCloud/arm_support
Browse files Browse the repository at this point in the history
Move simd under a feature flag, use fast CharLookup if not enabled
  • Loading branch information
FlorentinDUBOIS authored Aug 16, 2023
2 parents 68c22f4 + b74e75c commit 3f3e116
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 15 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ version = "0.6.2"
nom = "7.1.3"

[features]
# default = ["custom-vecdeque"]
default = ["simd"]
rc-alloc = []
custom-vecdeque = []
simd = []

[profile.release]
lto = true
Expand Down
18 changes: 9 additions & 9 deletions src/protocol/h1/parser/primitives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ fn http_status(i: &[u8]) -> IResult<&[u8], (&[u8], u16)> {
#[inline]
#[allow(clippy::type_complexity)]
pub fn parse_request_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], Version)> {
let (i, method) = tchar::take_while_simd(i)?;
let (i, method) = tchar::take_while_fast(i)?;
let (i, _) = space(i)?;
let (i, uri) = vchar::take_while_simd(i)?;
let (i, uri) = vchar::take_while_fast(i)?;
let (i, _) = space(i)?;
let (i, version) = http_version(i)?;
let (i, _) = crlf(i)?;
Expand All @@ -224,7 +224,7 @@ pub fn parse_response_line(i: &[u8]) -> IResult<&[u8], (Version, &[u8], u16, &[u
let (i, _) = space(i)?;
let (i, (status, code)) = http_status(i)?;
let (i, _) = space(i)?;
let (i, reason) = achar::take_while_simd(i)?;
let (i, reason) = achar::take_while_fast(i)?;
let (i, _) = crlf(i)?;
Ok((i, (version, status, code, reason)))
}
Expand All @@ -236,13 +236,13 @@ pub fn parse_response_line(i: &[u8]) -> IResult<&[u8], (Version, &[u8], u16, &[u
#[inline]
#[allow(clippy::type_complexity)]
pub fn parse_header_or_cookie(i: &[u8]) -> IResult<&[u8], Option<(&[u8], &[u8])>> {
let (i, key) = tchar::take_while_simd(i)?;
let (i, key) = tchar::take_while_fast(i)?;
let (i, _) = tag(b":")(i)?;
let (i, _) = take_while(is_space)(i)?;
if compare_no_case(key, b"cookie") {
return Ok((i, None));
}
let (i, val) = achar::take_while_simd(i)?;
let (i, val) = achar::take_while_fast(i)?;
let (i, _) = crlf(i)?;
Ok((i, Some((key, val))))
}
Expand All @@ -253,10 +253,10 @@ pub fn parse_header_or_cookie(i: &[u8]) -> IResult<&[u8], Option<(&[u8], &[u8])>
/// example: `Content-Length: 42\r\n`
#[inline]
pub fn parse_header(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
let (i, key) = tchar::take_while_simd(i)?;
let (i, key) = tchar::take_while_fast(i)?;
let (i, _) = tag(b":")(i)?;
let (i, _) = take_while(is_space)(i)?;
let (i, val) = achar::take_while_simd(i)?;
let (i, val) = achar::take_while_fast(i)?;
let (i, _) = crlf(i)?;
Ok((i, (key, val)))
}
Expand All @@ -277,8 +277,8 @@ pub fn parse_single_crumb(i: &[u8], first: bool) -> IResult<&[u8], (&[u8], &[u8]
} else {
i
};
let (i, key) = ck_char::take_while_simd(i)?;
let (i, val) = opt(tuple((tag(b"="), cv_char::take_while_simd)))(i)?;
let (i, key) = ck_char::take_while_fast(i)?;
let (i, val) = opt(tuple((tag(b"="), cv_char::take_while_fast)))(i)?;

match val {
Some((_, val)) => Ok((i, (key, val))),
Expand Down
80 changes: 75 additions & 5 deletions src/protocol/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ macro_rules! compile_lookup {
mod $name {
use $crate::h1::parser::primitives::{CharLookup, CharRanges, CharTable};
pub const LOOKUP: CharLookup = $crate::make_char_lookup!($($t)*);
pub const RANGES: CharRanges = LOOKUP.ranges;
pub const TABLE: CharTable = LOOKUP.table;
#[allow(dead_code)]
pub const RANGES: CharRanges = LOOKUP.ranges;
#[allow(dead_code)]
pub const LENGTH: i32 = LOOKUP.len;

#[inline]
Expand All @@ -115,11 +117,11 @@ macro_rules! compile_lookup {
}

#[inline]
#[allow(dead_code)]
#[cfg(feature="simd")]
/// Returns the longest string that fits the rule (simd optimized)
///
/// *Streaming version* will return a Err::Incomplete(Needed::Unknown) if the pattern reaches the end of the input.
pub fn take_while_simd(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
fn take_while_simd(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
use std::arch::x86_64::{
_mm_cmpestri, _mm_lddqu_si128, _mm_loadu_si128, _SIDD_CMP_RANGES,
_SIDD_LEAST_SIGNIFICANT, _SIDD_UBYTE_OPS,
Expand Down Expand Up @@ -173,9 +175,9 @@ macro_rules! compile_lookup {
}

#[inline]
#[allow(dead_code)]
#[cfg(feature="simd")]
/// Returns the longest string that fits the rule (simd optimized)
pub fn take_while_complete_simd(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
fn take_while_complete_simd(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
use std::arch::x86_64::{
_mm_cmpestri, _mm_lddqu_si128, _mm_loadu_si128, _SIDD_CMP_RANGES,
_SIDD_LEAST_SIGNIFICANT, _SIDD_UBYTE_OPS,
Expand Down Expand Up @@ -223,6 +225,74 @@ macro_rules! compile_lookup {
))
}
}

#[inline]
#[allow(dead_code)]
/// Returns the longest string that fits the rule (not simd optimized)
///
/// *Streaming version* will return a Err::Incomplete(Needed::Unknown) if the pattern reaches the end of the input.
pub fn take_while(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
let mut i = 0;
while i < input.len() {
if unsafe { !TABLE.get_unchecked(*input.get_unchecked(i) as usize) } {
break;
}
i += 1;
}
if i == input.len() {
return Err(nom::Err::Incomplete(nom::Needed::Unknown));
} else {
unsafe {
Ok((
input.get_unchecked(i..),
input.get_unchecked(..i),
))
}
}
}

#[inline]
#[allow(dead_code)]
/// Returns the longest string that fits the rule (not simd optimized)
pub fn take_while_complete(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
let mut i = 0;
while i < input.len() {
if unsafe { !TABLE.get_unchecked(*input.get_unchecked(i) as usize) } {
break;
}
i += 1;
}
unsafe {
Ok((
input.get_unchecked(i..),
input.get_unchecked(..i),
))
}
}

#[inline]
#[allow(dead_code)]
/// Returns the longest string that fits the rule (using simd if enabled)
///
/// *Streaming version* will return a Err::Incomplete(Needed::Unknown) if the pattern reaches the end of the input.
pub fn take_while_fast(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
#[cfg(feature="simd")]
let result = take_while_simd(input);
#[cfg(not(feature="simd"))]
let result = take_while(input);
result
}

#[inline]
#[allow(dead_code)]
/// Returns the longest string that fits the rule (using simd if enabled)
pub fn take_while_complete_fast(input: &[u8]) -> nom::IResult<&[u8], &[u8]> {
#[cfg(feature="simd")]
let result = take_while_complete_simd(input);
#[cfg(not(feature="simd"))]
let result = take_while_complete(input);
result
}
}
}
}

0 comments on commit 3f3e116

Please sign in to comment.