mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
aquatic http protocol: request parsing: remove hashmap for performance
request-from-bytes: time: [720.22 ns 723.34 ns 726.73 ns] change: [-53.265% -52.884% -52.477%] (p = 0.00 < 0.01) Performance has improved.
This commit is contained in:
parent
289cc4fcb5
commit
8fea96bcd2
6 changed files with 1057 additions and 1095 deletions
|
|
@ -1,5 +1,4 @@
|
|||
use anyhow::Context;
|
||||
use hashbrown::HashMap;
|
||||
use smartstring::{SmartString, LazyCompact};
|
||||
|
||||
use super::common::*;
|
||||
|
|
@ -169,94 +168,16 @@ impl Request {
|
|||
let query_string = split_parts.next()
|
||||
.with_context(|| "no query string")?;
|
||||
|
||||
// -- Parse key-value pairs
|
||||
|
||||
let mut info_hashes = Vec::new();
|
||||
let mut opt_peer_id = None;
|
||||
let mut data = HashMap::new();
|
||||
let mut opt_port = None;
|
||||
let mut opt_bytes_left = None;
|
||||
let mut event = AnnounceEvent::default();
|
||||
let mut opt_numwant = None;
|
||||
let mut opt_key = None;
|
||||
|
||||
Self::parse_key_value_pairs_memchr(
|
||||
&mut info_hashes,
|
||||
&mut opt_peer_id,
|
||||
&mut data,
|
||||
query_string
|
||||
)?;
|
||||
|
||||
if location == "/announce" {
|
||||
let numwant = if let Some(s) = data.remove("numwant"){
|
||||
let numwant = s.parse::<usize>()
|
||||
.map_err(|err|
|
||||
anyhow::anyhow!("parse 'numwant': {}", err)
|
||||
)?;
|
||||
|
||||
Some(numwant)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let key = if let Some(s) = data.remove("key"){
|
||||
if s.len() > 100 {
|
||||
return Err(anyhow::anyhow!("'key' is too long"))
|
||||
}
|
||||
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let port = if let Some(port) = data.remove("port"){
|
||||
port.parse().with_context(|| "parse port")?
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("no port"));
|
||||
};
|
||||
let bytes_left = if let Some(left) = data.remove("left"){
|
||||
left.parse().with_context(|| "parse bytes left")?
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("no left"));
|
||||
};
|
||||
let event = if let Some(event) = data.remove("event"){
|
||||
if let Ok(event) = event.parse(){
|
||||
event
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("invalid event: {}", event));
|
||||
}
|
||||
} else {
|
||||
AnnounceEvent::default()
|
||||
};
|
||||
let compact = if let Some(compact) = data.remove("compact"){
|
||||
if compact.as_str() == "1" {
|
||||
true
|
||||
} else {
|
||||
return Err(anyhow::anyhow!("compact set, but not to 1"));
|
||||
}
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
let request = AnnounceRequest {
|
||||
info_hash: info_hashes.pop().with_context(|| "no info_hash")?,
|
||||
peer_id: opt_peer_id.with_context(|| "no peer_id")?,
|
||||
port,
|
||||
bytes_left,
|
||||
event,
|
||||
compact,
|
||||
numwant,
|
||||
key,
|
||||
};
|
||||
|
||||
Ok(Request::Announce(request))
|
||||
} else {
|
||||
let request = ScrapeRequest {
|
||||
info_hashes,
|
||||
};
|
||||
|
||||
Ok(Request::Scrape(request))
|
||||
}
|
||||
}
|
||||
|
||||
/// Seems to be somewhat faster than non-memchr version
|
||||
fn parse_key_value_pairs_memchr<'a>(
|
||||
info_hashes: &mut Vec<InfoHash>,
|
||||
opt_peer_id: &mut Option<PeerId>,
|
||||
data: &mut HashMap<&'a str, SmartString<LazyCompact>>,
|
||||
query_string: &'a str,
|
||||
) -> anyhow::Result<()> {
|
||||
let query_string_bytes = query_string.as_bytes();
|
||||
|
||||
let mut ampersand_iter = ::memchr::memchr_iter(b'&', query_string_bytes);
|
||||
|
|
@ -271,7 +192,6 @@ impl Request {
|
|||
let value = query_string.get(equal_sign_index + 1..segment_end)
|
||||
.with_context(|| format!("no value at {}..{}", equal_sign_index + 1, segment_end))?;
|
||||
|
||||
// whitelist keys to avoid having to use ddos-resistant hashmap
|
||||
match key {
|
||||
"info_hash" => {
|
||||
let value = Self::urldecode_20_bytes(value)?;
|
||||
|
|
@ -281,10 +201,32 @@ impl Request {
|
|||
"peer_id" => {
|
||||
let value = Self::urldecode_20_bytes(value)?;
|
||||
|
||||
*opt_peer_id = Some(PeerId(value));
|
||||
opt_peer_id = Some(PeerId(value));
|
||||
},
|
||||
"port" | "left" | "event" | "compact" | "numwant" | "key" => {
|
||||
data.insert(key, value.into());
|
||||
"port" => {
|
||||
opt_port = Some(value.parse::<u16>().with_context(|| "parse port")?);
|
||||
},
|
||||
"left" => {
|
||||
opt_bytes_left = Some(value.parse::<usize>().with_context(|| "parse left")?);
|
||||
},
|
||||
"event" => {
|
||||
event = value.parse::<AnnounceEvent>().map_err(|err|
|
||||
anyhow::anyhow!("invalid event: {}", err)
|
||||
)?;
|
||||
},
|
||||
"compact" => {
|
||||
if value != "1" {
|
||||
return Err(anyhow::anyhow!("compact set, but not to 1"));
|
||||
}
|
||||
},
|
||||
"numwant" => {
|
||||
opt_numwant = Some(value.parse::<usize>().with_context(|| "parse numwant")?);
|
||||
},
|
||||
"key" => {
|
||||
if value.len() > 100 {
|
||||
return Err(anyhow::anyhow!("'key' is too long"))
|
||||
}
|
||||
opt_key = Some(value.into());
|
||||
},
|
||||
k => {
|
||||
::log::info!("ignored unrecognized key: {}", k)
|
||||
|
|
@ -298,7 +240,28 @@ impl Request {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
// -- Put together request
|
||||
|
||||
if location == "/announce" {
|
||||
let request = AnnounceRequest {
|
||||
info_hash: info_hashes.pop().with_context(|| "no info_hash")?,
|
||||
peer_id: opt_peer_id.with_context(|| "no peer_id")?,
|
||||
port: opt_port.with_context(|| "no port")?,
|
||||
bytes_left: opt_bytes_left.with_context(|| "no left")?,
|
||||
event,
|
||||
compact: true,
|
||||
numwant: opt_numwant,
|
||||
key: opt_key,
|
||||
};
|
||||
|
||||
Ok(Request::Announce(request))
|
||||
} else {
|
||||
let request = ScrapeRequest {
|
||||
info_hashes,
|
||||
};
|
||||
|
||||
Ok(Request::Scrape(request))
|
||||
}
|
||||
}
|
||||
|
||||
/// The info hashes and peer id's that are received are url-encoded byte
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"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}}
|
||||
{"mean":{"confidence_interval":{"confidence_level":0.95,"lower_bound":725.4551837276395,"upper_bound":735.0471255185286},"point_estimate":730.0304941357815,"standard_error":2.44315882364003},"median":{"confidence_interval":{"confidence_level":0.95,"lower_bound":710.2692059508443,"upper_bound":713.9114247675105},"point_estimate":711.6918749031568,"standard_error":0.939200067715216},"median_abs_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":21.74599816051584,"upper_bound":25.76476135212916},"point_estimate":23.51684998144059,"standard_error":1.0048983533788292},"slope":{"confidence_interval":{"confidence_level":0.95,"lower_bound":720.2235427692906,"upper_bound":726.7290589621539},"point_estimate":723.3388090543597,"standard_error":1.655406933329102},"std_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":60.65633946284278,"upper_bound":94.33752282501924},"point_estimate":77.10614491661927,"standard_error":8.653988561946822}}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
[1272.4120390677972,1377.6532072370742,1658.2963223551465,1763.5374905244237]
|
||||
[598.8933477988796,648.0355807205904,779.0815351784856,828.2237681001964]
|
||||
Loading…
Add table
Add a link
Reference in a new issue