mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
aquatic_http: serialize responses to a buffer ref instead of new vec
This improves benchmark performance somewhat and performance during load testing a bit too.
This commit is contained in:
parent
228511b3aa
commit
fd68a5f603
7 changed files with 1101 additions and 1089 deletions
|
|
@ -26,9 +26,14 @@ pub fn bench(c: &mut Criterion) {
|
|||
|
||||
let response = Response::Announce(announce_response);
|
||||
|
||||
c.bench_function("announce-response-to-bytes", |b| b.iter(||
|
||||
Response::to_bytes(black_box(&response))
|
||||
));
|
||||
let mut buffer = [0u8; 4096];
|
||||
let mut buffer = ::std::io::Cursor::new(&mut buffer[..]);
|
||||
|
||||
c.bench_function("announce-response-to-bytes", |b| b.iter(|| {
|
||||
buffer.set_position(0);
|
||||
|
||||
Response::write(black_box(&response), black_box(&mut buffer)).unwrap();
|
||||
}));
|
||||
}
|
||||
|
||||
criterion_group!{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use std::io::Write;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use serde::Serialize;
|
||||
|
|
@ -50,51 +51,50 @@ pub struct AnnounceResponse {
|
|||
|
||||
|
||||
impl AnnounceResponse {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
let peers_bytes_len = self.peers.0.len() * 6;
|
||||
let peers6_bytes_len = self.peers6.0.len() * 18;
|
||||
fn write<W: Write>(&self, output: &mut W) -> ::std::io::Result<usize> {
|
||||
let mut bytes_written = 0usize;
|
||||
|
||||
let mut bytes = Vec::with_capacity(
|
||||
12 +
|
||||
5 + // Upper estimate
|
||||
15 +
|
||||
5 + // Upper estimate
|
||||
12 +
|
||||
5 + // Upper estimate
|
||||
8 +
|
||||
peers_bytes_len +
|
||||
8 +
|
||||
peers6_bytes_len +
|
||||
1
|
||||
);
|
||||
bytes_written += output.write(b"d8:completei")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(self.complete).as_bytes()
|
||||
)?;
|
||||
|
||||
bytes.extend_from_slice(b"d8:completei");
|
||||
let _ = itoa::write(&mut bytes, self.complete);
|
||||
bytes_written += output.write(b"e10:incompletei")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(self.incomplete).as_bytes()
|
||||
)?;
|
||||
|
||||
bytes.extend_from_slice(b"e10:incompletei");
|
||||
let _ = itoa::write(&mut bytes, self.incomplete);
|
||||
bytes_written += output.write(b"e8:intervali")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(self.announce_interval).as_bytes()
|
||||
)?;
|
||||
|
||||
bytes.extend_from_slice(b"e8:intervali");
|
||||
let _ = itoa::write(&mut bytes, self.announce_interval);
|
||||
|
||||
bytes.extend_from_slice(b"e5:peers");
|
||||
let _ = itoa::write(&mut bytes, peers_bytes_len);
|
||||
bytes.push(b':');
|
||||
bytes_written += output.write(b"e5:peers")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(self.peers.0.len() * 6).as_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(b":")?;
|
||||
for peer in self.peers.0.iter() {
|
||||
bytes.extend_from_slice(&u32::from(peer.ip_address).to_be_bytes());
|
||||
bytes.extend_from_slice(&peer.port.to_be_bytes())
|
||||
bytes_written += output.write(
|
||||
&u32::from(peer.ip_address).to_be_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(&peer.port.to_be_bytes())?;
|
||||
}
|
||||
|
||||
bytes.extend_from_slice(b"6:peers6");
|
||||
let _ = itoa::write(&mut bytes, peers6_bytes_len);
|
||||
bytes.push(b':');
|
||||
bytes_written += output.write(b"6:peers6")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(self.peers6.0.len() * 18).as_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(b":")?;
|
||||
for peer in self.peers6.0.iter() {
|
||||
bytes.extend_from_slice(&u128::from(peer.ip_address).to_be_bytes());
|
||||
bytes.extend_from_slice(&peer.port.to_be_bytes())
|
||||
bytes_written += output.write(
|
||||
&u128::from(peer.ip_address).to_be_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(&peer.port.to_be_bytes())?;
|
||||
}
|
||||
bytes.push(b'e');
|
||||
bytes_written += output.write(b"e")?;
|
||||
|
||||
bytes
|
||||
Ok(bytes_written)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,36 +107,28 @@ pub struct ScrapeResponse {
|
|||
|
||||
|
||||
impl ScrapeResponse {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::with_capacity(
|
||||
9 +
|
||||
self.files.len() * (
|
||||
3 +
|
||||
20 +
|
||||
12 +
|
||||
5 + // Upper estimate
|
||||
31 +
|
||||
5 + // Upper estimate
|
||||
2
|
||||
) +
|
||||
2
|
||||
);
|
||||
fn write<W: Write>(&self, output: &mut W) -> ::std::io::Result<usize> {
|
||||
let mut bytes_written = 0usize;
|
||||
|
||||
bytes.extend_from_slice(b"d5:filesd");
|
||||
bytes_written += output.write(b"d5:filesd")?;
|
||||
|
||||
for (info_hash, statistics) in self.files.iter(){
|
||||
bytes.extend_from_slice(b"20:");
|
||||
bytes.extend_from_slice(&info_hash.0);
|
||||
bytes.extend_from_slice(b"d8:completei");
|
||||
let _ = itoa::write(&mut bytes, statistics.complete);
|
||||
bytes.extend_from_slice(b"e10:downloadedi0e10:incompletei");
|
||||
let _ = itoa::write(&mut bytes, statistics.incomplete);
|
||||
bytes.extend_from_slice(b"ee");
|
||||
bytes_written += output.write(b"20:")?;
|
||||
bytes_written += output.write(&info_hash.0)?;
|
||||
bytes_written += output.write(b"d8:completei")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(statistics.complete).as_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(b"e10:downloadedi0e10:incompletei")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(statistics.incomplete).as_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(b"ee")?;
|
||||
}
|
||||
|
||||
bytes.extend_from_slice(b"ee");
|
||||
bytes_written += output.write(b"ee")?;
|
||||
|
||||
bytes
|
||||
Ok(bytes_written)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,24 +140,20 @@ pub struct FailureResponse {
|
|||
|
||||
|
||||
impl FailureResponse {
|
||||
fn to_bytes(&self) -> Vec<u8> {
|
||||
fn write<W: Write>(&self, output: &mut W) -> ::std::io::Result<usize> {
|
||||
let mut bytes_written = 0usize;
|
||||
|
||||
let reason_bytes = self.failure_reason.as_bytes();
|
||||
|
||||
let mut bytes = Vec::with_capacity(
|
||||
18 +
|
||||
3 + // Upper estimate
|
||||
1 +
|
||||
reason_bytes.len() +
|
||||
1
|
||||
);
|
||||
bytes_written += output.write(b"d14:failure_reason")?;
|
||||
bytes_written += output.write(
|
||||
itoa::Buffer::new().format(reason_bytes.len()).as_bytes()
|
||||
)?;
|
||||
bytes_written += output.write(b":")?;
|
||||
bytes_written += output.write(reason_bytes)?;
|
||||
bytes_written += output.write(b"e")?;
|
||||
|
||||
bytes.extend_from_slice(b"d14:failure_reason");
|
||||
let _ = itoa::write(&mut bytes, reason_bytes.len());
|
||||
bytes.push(b':');
|
||||
bytes.extend_from_slice(reason_bytes);
|
||||
bytes.push(b'e');
|
||||
|
||||
bytes
|
||||
Ok(bytes_written)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,11 +168,11 @@ pub enum Response {
|
|||
|
||||
|
||||
impl Response {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
pub fn write<W: Write>(&self, output: &mut W) -> ::std::io::Result<usize> {
|
||||
match self {
|
||||
Response::Announce(r) => r.to_bytes(),
|
||||
Response::Failure(r) => r.to_bytes(),
|
||||
Response::Scrape(r) => r.to_bytes(),
|
||||
Response::Announce(r) => r.write(output),
|
||||
Response::Failure(r) => r.write(output),
|
||||
Response::Scrape(r) => r.write(output),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -286,7 +274,11 @@ mod tests {
|
|||
&Response::Announce(response.clone())
|
||||
).unwrap();
|
||||
|
||||
response.to_bytes() == reference
|
||||
let mut output = Vec::new();
|
||||
|
||||
response.write(&mut output).unwrap();
|
||||
|
||||
output == reference
|
||||
}
|
||||
|
||||
#[quickcheck]
|
||||
|
|
@ -294,7 +286,10 @@ mod tests {
|
|||
let reference = bendy::serde::to_bytes(
|
||||
&Response::Scrape(response.clone())
|
||||
).unwrap();
|
||||
let hand_written = response.to_bytes();
|
||||
|
||||
let mut hand_written = Vec::new();
|
||||
|
||||
response.write(&mut hand_written).unwrap();
|
||||
|
||||
let success = hand_written == reference;
|
||||
|
||||
|
|
@ -312,6 +307,10 @@ mod tests {
|
|||
&Response::Failure(response.clone())
|
||||
).unwrap();
|
||||
|
||||
response.to_bytes() == reference
|
||||
let mut output = Vec::new();
|
||||
|
||||
response.write(&mut output).unwrap();
|
||||
|
||||
output == reference
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
{"mean":{"confidence_interval":{"confidence_level":0.95,"lower_bound":679.6199835027244,"upper_bound":683.1765435179024},"point_estimate":681.3262892361256,"standard_error":0.9087088681117722},"median":{"confidence_interval":{"confidence_level":0.95,"lower_bound":675.1429773039165,"upper_bound":678.0182057889292},"point_estimate":676.3105408394639,"standard_error":0.6854649236080195},"median_abs_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":22.428283556649202,"upper_bound":25.203260654300284},"point_estimate":24.35095483756527,"standard_error":0.69150074330993},"slope":{"confidence_interval":{"confidence_level":0.95,"lower_bound":672.118472824725,"upper_bound":677.6479220619163},"point_estimate":674.6741040360789,"standard_error":1.4165525766541145},"std_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":23.51653893971022,"upper_bound":33.64225930231783},"point_estimate":28.565599471881452,"standard_error":2.588927502189203}}
|
||||
{"mean":{"confidence_interval":{"confidence_level":0.95,"lower_bound":658.5830856810967,"upper_bound":662.6140140431078},"point_estimate":660.5315794423136,"standard_error":1.0267544650468448},"median":{"confidence_interval":{"confidence_level":0.95,"lower_bound":645.305767448625,"upper_bound":648.8067825908649},"point_estimate":646.7621214660466,"standard_error":0.965885560495337},"median_abs_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":8.471955633936192,"upper_bound":13.107607852360173},"point_estimate":10.494262498769816,"standard_error":1.2403366025964986},"slope":{"confidence_interval":{"confidence_level":0.95,"lower_bound":657.1689080616346,"upper_bound":661.4062067913236},"point_estimate":659.2109887653004,"standard_error":1.0812556505845492},"std_dev":{"confidence_interval":{"confidence_level":0.95,"lower_bound":26.296406154649638,"upper_bound":39.21798204128364},"point_estimate":32.5892125764255,"standard_error":3.3046616744256077}}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
[560.1173877793271,609.6904444532156,741.8852622502513,791.4583189241397]
|
||||
[555.2496610557599,598.3305180332976,713.2128033067314,756.2936602842691]
|
||||
Loading…
Add table
Add a link
Reference in a new issue