From a78dfd8ecc68b9aabe6f5ea20d92daf5f44bd800 Mon Sep 17 00:00:00 2001 From: neetdai <> Date: Sun, 19 Jan 2025 22:51:37 +0800 Subject: [PATCH] Add memchr and optimize resp2 decode --- Cargo.toml | 7 ++++--- src/resp2/decode.rs | 15 ++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f54978..5f9e18c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ nom = { version = "7.1", default-features = false } libm = { version = "0.2", optional = true } hashbrown = { version = "0.14", optional = true } tokio-util = { version = "0.7", features = ["codec"], optional = true } +memchr = "2.7.4" [dev-dependencies] rand = "0.8" @@ -60,9 +61,9 @@ doctest = true name = "redis_protocol" test = true -#[[bench]] -#name = "resp2_decode" -#harness = false +[[bench]] +name = "resp2_decode" +harness = false #[[bench]] #name = "resp2_encode" diff --git a/src/resp2/decode.rs b/src/resp2/decode.rs index d88c777..a76c92f 100644 --- a/src/resp2/decode.rs +++ b/src/resp2/decode.rs @@ -9,7 +9,8 @@ use crate::{ utils, }; use alloc::vec::Vec; -use core::str; +use memchr::memchr; +use core::{num::NonZero, str}; use nom::{ bytes::streaming::{take as nom_take, take_until as nom_take_until}, multi::count as nom_count, @@ -39,13 +40,20 @@ fn to_i64(s: &[u8]) -> Result> { fn d_read_to_crlf(input: (&[u8], usize)) -> DResult { decode_log_str!(input.0, _input, "Parsing to CRLF. Remaining: {:?}", _input); - let (input_bytes, data) = nom_terminated(nom_take_until(CRLF.as_bytes()), nom_take(2_usize))(input.0)?; + // let (input_bytes, data) = nom_terminated(nom_take_until(CRLF.as_bytes()), nom_take(2_usize))(input.0)?; + let position = memchr(b'\r', input.0).ok_or_else(|| NomErr::Error(RedisParseError::Nom(input.0, nom::error::ErrorKind::CrLf)))?; + let (data, input_bytes) = input.0.split_at(position); + let (_, input_bytes) = input_bytes.split_at_checked(2).ok_or_else(|| NomErr::Error(RedisParseError::Nom(input.0, nom::error::ErrorKind::Eof)))?; Ok(((input_bytes, input.1 + data.len() + 2), data.len())) } +#[inline] fn d_read_to_crlf_take(input: (&[u8], usize)) -> DResult<&[u8]> { decode_log_str!(input.0, _input, "Parsing to CRLF. Remaining: {:?}", _input); - let (input_bytes, data) = nom_terminated(nom_take_until(CRLF.as_bytes()), nom_take(2_usize))(input.0)?; + // let (input_bytes, data) = nom_terminated(nom_take_until(CRLF.as_bytes()), nom_take(2_usize))(input.0)?; + let position = memchr(b'\r', input.0).ok_or_else(|| NomErr::Error(RedisParseError::Nom(input.0, nom::error::ErrorKind::CrLf)))?; + let (data, input_bytes) = input.0.split_at(position); + let (_, input_bytes) = input_bytes.split_at_checked(2).ok_or_else(|| NomErr::Error(RedisParseError::Nom(input.0, nom::error::ErrorKind::Eof)))?; Ok(((input_bytes, input.1 + data.len() + 2), data)) } @@ -100,6 +108,7 @@ fn d_parse_error(input: (&[u8], usize)) -> DResult { Ok(((input, next_offset), RangeFrame::Error((offset, offset + len)))) } +#[inline] fn d_parse_bulkstring(input: (&[u8], usize), len: usize) -> DResult { let offset = input.1; let (input, data) = nom_terminated(nom_take(len), nom_take(2_usize))(input.0)?;