mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
aquatic http protocol: optimize request parsing
request-from-bytes: time: [1.5288 us 1.5362 us 1.5441 us] change: [-38.029% -37.466% -36.890%] (p = 0.00 < 0.01) Performance has improved.
This commit is contained in:
parent
87328f788d
commit
b7d5a12046
5 changed files with 1064 additions and 1024 deletions
|
|
@ -174,10 +174,12 @@ impl Request {
|
|||
.with_context(|| "no query string")?;
|
||||
|
||||
let mut info_hashes = Vec::new();
|
||||
let mut opt_peer_id = None;
|
||||
let mut data = HashMap::new();
|
||||
|
||||
Self::parse_key_value_pairs_memchr(
|
||||
&mut info_hashes,
|
||||
&mut opt_peer_id,
|
||||
&mut data,
|
||||
query_string
|
||||
)?;
|
||||
|
|
@ -232,14 +234,8 @@ impl Request {
|
|||
};
|
||||
|
||||
let request = AnnounceRequest {
|
||||
info_hash: info_hashes.pop()
|
||||
.with_context(|| "no info_hash")
|
||||
.and_then(deserialize_20_bytes)
|
||||
.map(InfoHash)?,
|
||||
peer_id: data.remove("peer_id")
|
||||
.with_context(|| "no peer_id")
|
||||
.and_then(deserialize_20_bytes)
|
||||
.map(PeerId)?,
|
||||
info_hash: info_hashes.pop().with_context(|| "no info_hash")?,
|
||||
peer_id: opt_peer_id.with_context(|| "no peer_id")?,
|
||||
port,
|
||||
bytes_left,
|
||||
event,
|
||||
|
|
@ -250,14 +246,8 @@ impl Request {
|
|||
|
||||
Ok(Request::Announce(request))
|
||||
} else {
|
||||
let mut parsed_info_hashes = Vec::with_capacity(info_hashes.len());
|
||||
|
||||
for info_hash in info_hashes {
|
||||
parsed_info_hashes.push(InfoHash(deserialize_20_bytes(info_hash)?));
|
||||
}
|
||||
|
||||
let request = ScrapeRequest {
|
||||
info_hashes: parsed_info_hashes,
|
||||
info_hashes,
|
||||
};
|
||||
|
||||
Ok(Request::Scrape(request))
|
||||
|
|
@ -266,7 +256,8 @@ impl Request {
|
|||
|
||||
/// Seems to be somewhat faster than non-memchr version
|
||||
fn parse_key_value_pairs_memchr<'a>(
|
||||
info_hashes: &mut Vec<SmartString<LazyCompact>>,
|
||||
info_hashes: &mut Vec<InfoHash>,
|
||||
opt_peer_id: &mut Option<PeerId>,
|
||||
data: &mut HashMap<&'a str, SmartString<LazyCompact>>,
|
||||
query_string: &'a str,
|
||||
) -> anyhow::Result<()> {
|
||||
|
|
@ -287,14 +278,17 @@ impl Request {
|
|||
// whitelist keys to avoid having to use ddos-resistant hashmap
|
||||
match key {
|
||||
"info_hash" => {
|
||||
let value = Self::urldecode_memchr(value)?;
|
||||
let value = Self::urldecode_20_bytes(value)?;
|
||||
|
||||
info_hashes.push(value);
|
||||
info_hashes.push(InfoHash(value));
|
||||
},
|
||||
"peer_id" | "port" | "left" | "event" | "compact" | "numwant" | "key" => {
|
||||
let value = Self::urldecode_memchr(value)?;
|
||||
"peer_id" => {
|
||||
let value = Self::urldecode_20_bytes(value)?;
|
||||
|
||||
data.insert(key, value);
|
||||
*opt_peer_id = Some(PeerId(value));
|
||||
},
|
||||
"port" | "left" | "event" | "compact" | "numwant" | "key" => {
|
||||
data.insert(key, value.into());
|
||||
},
|
||||
k => {
|
||||
::log::info!("ignored unrecognized key: {}", k)
|
||||
|
|
@ -386,6 +380,52 @@ impl Request {
|
|||
Ok(processed)
|
||||
}
|
||||
|
||||
fn urldecode_20_bytes(value: &str) -> anyhow::Result<[u8; 20]> {
|
||||
let mut out_arr = [0u8; 20];
|
||||
|
||||
let mut chars = value.chars();
|
||||
|
||||
for i in 0..20 {
|
||||
let c = chars.next()
|
||||
.with_context(|| "less than 20 chars")?;
|
||||
|
||||
if c as u32 > 255 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"character not in single byte range: {:#?}",
|
||||
c
|
||||
));
|
||||
}
|
||||
|
||||
if c == '%' {
|
||||
let first = chars.next()
|
||||
.with_context(|| "missing first urldecode char in pair")?;
|
||||
let second = chars.next()
|
||||
.with_context(|| "missing second urldecode char in pair")?;
|
||||
|
||||
let hex = [first as u8, second as u8];
|
||||
|
||||
hex::decode_to_slice(&hex, &mut out_arr[i..i+1]).map_err(|err|
|
||||
anyhow::anyhow!("hex decode error: {:?}", err)
|
||||
)?;
|
||||
} else {
|
||||
if c as u32 > 255 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"character not in single byte range: {:#?}",
|
||||
c
|
||||
));
|
||||
}
|
||||
|
||||
out_arr[i] = c as u8;
|
||||
}
|
||||
}
|
||||
|
||||
if chars.next().is_some(){
|
||||
return Err(anyhow::anyhow!("more than 20 chars"));
|
||||
}
|
||||
|
||||
Ok(out_arr)
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
match self {
|
||||
Self::Announce(r) => r.as_bytes(),
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"mean":{"confidence_interval":{"confidence_level":0.95,"lower_bound":2460.1209520234065,"upper_bound":2496.3120750993653},"point_estimate":2477.735012452959,"standard_error":9.223219637832466},"median":{"confidence_interval":{"confidence_level":0.95,"lower_bound":2378.552109650183,"upper_bound":2392.9167858884143},"point_estimate":2386.0253054074483,"standard_error":3.7683770634335887},"median_abs_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":99.96596815329639,"upper_bound":120.92540240951352},"point_estimate":110.60694919175964,"standard_error":5.3506476356761885},"slope":{"confidence_interval":{"confidence_level":0.95,"lower_bound":2438.3485065067393,"upper_bound":2469.501606349259},"point_estimate":2453.4596391963023,"standard_error":7.977121580504992},"std_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":251.73297824646409,"upper_bound":332.1546916341356},"point_estimate":291.46617601681515,"standard_error":20.531098767805926}}
|
||||
{"mean":{"confidence_interval":{"confidence_level":0.95,"lower_bound":1540.8390649054281,"upper_bound":1558.4887891210565},"point_estimate":1549.4245398703538,"standard_error":4.517692089474024},"median":{"confidence_interval":{"confidence_level":0.95,"lower_bound":1506.8523919746872,"upper_bound":1513.8541497552624},"point_estimate":1510.1168042545828,"standard_error":1.754123550033509},"median_abs_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":45.152694401086514,"upper_bound":54.71728947836145},"point_estimate":49.43491905391041,"standard_error":2.470252770404891},"slope":{"confidence_interval":{"confidence_level":0.95,"lower_bound":1528.8205165274087,"upper_bound":1544.1141471464193},"point_estimate":1536.161119110567,"standard_error":3.9201641311296234},"std_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":121.9529239151999,"upper_bound":162.2045693733035},"point_estimate":142.20072433991157,"standard_error":10.304640393049143}}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
[1795.8747498180473,2061.4607369455734,2769.6900359523097,3035.276023079836]
|
||||
[1272.4120390677972,1377.6532072370742,1658.2963223551465,1763.5374905244237]
|
||||
Loading…
Add table
Add a link
Reference in a new issue