mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
bench_handlers: parially extract setup portions for better profiling
This commit is contained in:
parent
8c57b3c4fe
commit
a627594c3a
5 changed files with 127 additions and 121 deletions
7
TODO.md
7
TODO.md
|
|
@ -6,12 +6,13 @@
|
|||
* Cleaner code
|
||||
* Stack-allocated vector?
|
||||
* Benchmarks
|
||||
* Seperate setup so actual benchmarks can be run after each other,
|
||||
enabling better profiling
|
||||
* Move to own crate (aquatic_bench)
|
||||
* Better black_box (or make sure to consume data)
|
||||
* Show standard deviation?
|
||||
* Send in connect reponse ids to other functions as integration test
|
||||
* target-cpu=native
|
||||
|
||||
## Don't do
|
||||
|
||||
* Other hash algorithms: seemingly not worthwhile
|
||||
* Other hash algorithms: seemingly not worthwhile (might be with AVX though)
|
||||
* `sendmmsg`: can't send to multiple socket addresses, so doesn't help
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use std::time::{Duration, Instant};
|
||||
use std::time::Instant;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use rand::Rng;
|
||||
|
|
@ -15,41 +15,19 @@ const ANNOUNCE_REQUESTS: usize = 1_000_000;
|
|||
|
||||
|
||||
pub fn bench(
|
||||
rng: &mut impl Rng,
|
||||
state: &State,
|
||||
info_hashes: &Vec<InfoHash>
|
||||
requests: Vec<(AnnounceRequest, SocketAddr)>,
|
||||
) -> (f64, f64) {
|
||||
println!("## benchmark: handle_announce_requests\n");
|
||||
|
||||
println!("generating data..");
|
||||
|
||||
let mut responses = Vec::with_capacity(ANNOUNCE_REQUESTS);
|
||||
|
||||
let mut announce_requests = create_announce_requests(rng, &info_hashes);
|
||||
|
||||
let time = Time(Instant::now());
|
||||
|
||||
for (request, src) in announce_requests.iter() {
|
||||
let key = ConnectionKey {
|
||||
connection_id: request.connection_id,
|
||||
socket_addr: *src,
|
||||
};
|
||||
|
||||
state.connections.insert(key, time);
|
||||
}
|
||||
|
||||
let announce_requests = announce_requests.drain(..);
|
||||
|
||||
::std::thread::sleep(Duration::from_millis(100));
|
||||
let mut requests = requests;
|
||||
let requests = requests.drain(..);
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
println!("running benchmark..");
|
||||
|
||||
handle_announce_requests(
|
||||
&state,
|
||||
&mut responses,
|
||||
announce_requests,
|
||||
requests,
|
||||
);
|
||||
|
||||
let duration = Instant::now() - now;
|
||||
|
|
@ -57,19 +35,17 @@ pub fn bench(
|
|||
let requests_per_second = ANNOUNCE_REQUESTS as f64 / (duration.as_millis() as f64 / 1000.0);
|
||||
let time_per_request = duration.as_nanos() as f64 / ANNOUNCE_REQUESTS as f64;
|
||||
|
||||
println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
println!("time per request: {:.2}ns", time_per_request);
|
||||
// println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
// println!("time per request: {:.2}ns", time_per_request);
|
||||
|
||||
let mut total_num_peers = 0.0f64;
|
||||
let mut max_num_peers = 0.0f64;
|
||||
// let mut total_num_peers = 0.0f64;
|
||||
let mut num_responses: usize = 0;
|
||||
|
||||
for (response, _src) in responses.drain(..) {
|
||||
if let Response::Announce(response) = response {
|
||||
let n = response.peers.len() as f64;
|
||||
if let Response::Announce(_response) = response {
|
||||
// let n = response.peers.len() as f64;
|
||||
|
||||
total_num_peers += n;
|
||||
max_num_peers = max_num_peers.max(n);
|
||||
// total_num_peers += n;
|
||||
num_responses += 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -78,15 +54,14 @@ pub fn bench(
|
|||
println!("ERROR: only {} responses received", num_responses);
|
||||
}
|
||||
|
||||
println!("avg num peers returned: {:.2}", total_num_peers / ANNOUNCE_REQUESTS as f64);
|
||||
println!("max num peers returned: {:.2}", max_num_peers);
|
||||
// println!("avg num peers returned: {:.2}", total_num_peers / ANNOUNCE_REQUESTS as f64);
|
||||
|
||||
(requests_per_second, time_per_request)
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn create_announce_requests(
|
||||
pub fn create_requests(
|
||||
rng: &mut impl Rng,
|
||||
info_hashes: &Vec<InfoHash>
|
||||
) -> Vec<(AnnounceRequest, SocketAddr)> {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::time::{Instant, Duration};
|
||||
use std::time::Instant;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use rand::{Rng, thread_rng, rngs::SmallRng, SeedableRng};
|
||||
|
|
@ -10,19 +10,14 @@ use aquatic::handlers::handle_connect_requests;
|
|||
const ITERATIONS: usize = 10_000_000;
|
||||
|
||||
|
||||
pub fn bench() -> (f64, f64){
|
||||
println!("## benchmark: handle_connect_requests\n");
|
||||
|
||||
pub fn bench(
|
||||
requests: Vec<(ConnectRequest, SocketAddr)>
|
||||
) -> (f64, f64){
|
||||
let state = State::new();
|
||||
let mut responses = Vec::new();
|
||||
|
||||
let mut requests = create_requests();
|
||||
let mut responses = Vec::with_capacity(ITERATIONS);
|
||||
let mut requests = requests;
|
||||
let requests = requests.drain(..);
|
||||
|
||||
println!("running benchmark..");
|
||||
|
||||
::std::thread::sleep(Duration::from_millis(100));
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
handle_connect_requests(&state, &mut responses, requests);
|
||||
|
|
@ -32,8 +27,8 @@ pub fn bench() -> (f64, f64){
|
|||
let requests_per_second = ITERATIONS as f64 / (duration.as_millis() as f64 / 1000.0);
|
||||
let time_per_request = duration.as_nanos() as f64 / ITERATIONS as f64;
|
||||
|
||||
println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
println!("time per request: {:.2}ns", time_per_request);
|
||||
// println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
// println!("time per request: {:.2}ns", time_per_request);
|
||||
|
||||
let mut dummy = 0usize;
|
||||
let mut num_responses: usize = 0;
|
||||
|
|
@ -60,7 +55,7 @@ pub fn bench() -> (f64, f64){
|
|||
}
|
||||
|
||||
|
||||
fn create_requests() -> Vec<(ConnectRequest, SocketAddr)> {
|
||||
pub fn create_requests() -> Vec<(ConnectRequest, SocketAddr)> {
|
||||
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
||||
|
||||
let mut requests = Vec::new();
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@
|
|||
//!
|
||||
//! Example summary output:
|
||||
//! ```
|
||||
//! # Average results over 20 rounds
|
||||
//!
|
||||
//! connect handler: 3 365 415 requests/second, 297.41 ns/request
|
||||
//! announce handler: 346 650 requests/second, 2921.76 ns/request
|
||||
//! scrape handler: 1 313 100 requests/second, 762.47 ns/request
|
||||
//! # Average results over 100 rounds
|
||||
//! connect handler: 3 201 147 requests/second, 312.66 ns/request
|
||||
//! announce handler: 330 958 requests/second, 3029.13 ns/request
|
||||
//! scrape handler: 1 242 478 requests/second, 805.62 ns/request
|
||||
//! ```
|
||||
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use num_format::{Locale, ToFormattedString};
|
||||
use rand::{Rng, thread_rng, rngs::SmallRng, SeedableRng};
|
||||
|
|
@ -44,44 +43,99 @@ macro_rules! print_results {
|
|||
|
||||
|
||||
fn main(){
|
||||
let num_rounds = 20;
|
||||
let num_rounds = 100;
|
||||
|
||||
let mut connect_data = (0.0, 0.0);
|
||||
let mut announce_data = (0.0, 0.0);
|
||||
let mut scrape_data = (0.0, 0.0);
|
||||
|
||||
for round in 0..num_rounds {
|
||||
println!("# Round {}/{}\n", round + 1, num_rounds);
|
||||
{
|
||||
let requests = connect::create_requests();
|
||||
|
||||
let d = connect::bench();
|
||||
connect_data.0 += d.0;
|
||||
connect_data.1 += d.1;
|
||||
::std::thread::sleep(Duration::from_secs(1));
|
||||
|
||||
println!("");
|
||||
for round in 0..num_rounds {
|
||||
println!("# Round {}/{}\n", round + 1, num_rounds);
|
||||
|
||||
::std::thread::sleep(Duration::from_millis(100));
|
||||
|
||||
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
||||
let info_hashes = create_info_hashes(&mut rng);
|
||||
let state = State::new();
|
||||
|
||||
let d = announce::bench(&mut rng, &state, &info_hashes);
|
||||
announce_data.0 += d.0;
|
||||
announce_data.1 += d.1;
|
||||
|
||||
state.connections.clear();
|
||||
|
||||
println!("");
|
||||
|
||||
::std::thread::sleep(Duration::from_millis(100));
|
||||
|
||||
let d = scrape::bench(&mut rng, &state, &info_hashes);
|
||||
scrape_data.0 += d.0;
|
||||
scrape_data.1 += d.1;
|
||||
|
||||
println!();
|
||||
let d = connect::bench(requests.clone());
|
||||
connect_data.0 += d.0;
|
||||
connect_data.1 += d.1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
||||
let info_hashes = create_info_hashes(&mut rng);
|
||||
|
||||
let state_for_scrape: State = {
|
||||
let requests = announce::create_requests(
|
||||
&mut rng,
|
||||
&info_hashes
|
||||
);
|
||||
|
||||
let mut state_for_scrape = State::new();
|
||||
|
||||
::std::thread::sleep(Duration::from_secs(1));
|
||||
|
||||
for round in 0..num_rounds {
|
||||
println!("# Round {}/{}\n", round + 1, num_rounds);
|
||||
|
||||
let state = State::new();
|
||||
|
||||
let time = Time(Instant::now());
|
||||
|
||||
for (request, src) in requests.iter() {
|
||||
let key = ConnectionKey {
|
||||
connection_id: request.connection_id,
|
||||
socket_addr: *src,
|
||||
};
|
||||
|
||||
state.connections.insert(key, time);
|
||||
}
|
||||
|
||||
let d = announce::bench(&state, requests.clone());
|
||||
announce_data.0 += d.0;
|
||||
announce_data.1 += d.1;
|
||||
|
||||
if round == num_rounds - 1 {
|
||||
state_for_scrape = state.clone();
|
||||
}
|
||||
}
|
||||
|
||||
state_for_scrape
|
||||
};
|
||||
|
||||
state_for_scrape.connections.clear();
|
||||
|
||||
{
|
||||
let state = state_for_scrape;
|
||||
|
||||
let requests = scrape::create_requests(&mut rng, &info_hashes);
|
||||
|
||||
let time = Time(Instant::now());
|
||||
|
||||
for (request, src) in requests.iter() {
|
||||
let key = ConnectionKey {
|
||||
connection_id: request.connection_id,
|
||||
socket_addr: *src,
|
||||
};
|
||||
|
||||
state.connections.insert(key, time);
|
||||
}
|
||||
|
||||
::std::thread::sleep(Duration::from_secs(1));
|
||||
|
||||
for round in 0..num_rounds {
|
||||
println!("# Round {}/{}\n", round + 1, num_rounds);
|
||||
|
||||
let d = scrape::bench(&state, requests.clone());
|
||||
scrape_data.0 += d.0;
|
||||
scrape_data.1 += d.1;
|
||||
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
println!("# Average results over {} rounds\n", num_rounds);
|
||||
|
||||
print_results!("connect handler: ", num_rounds, connect_data);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::time::{Duration, Instant};
|
||||
use std::time::Instant;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use rand::Rng;
|
||||
|
|
@ -16,32 +16,13 @@ const SCRAPE_NUM_HASHES: usize = 10;
|
|||
|
||||
|
||||
pub fn bench(
|
||||
rng: &mut impl Rng,
|
||||
state: &State,
|
||||
info_hashes: &Vec<InfoHash>
|
||||
requests: Vec<(ScrapeRequest, SocketAddr)>,
|
||||
) -> (f64, f64) {
|
||||
println!("## benchmark: handle_scrape_requests\n");
|
||||
println!("generating data..");
|
||||
|
||||
let mut responses = Vec::with_capacity(SCRAPE_REQUESTS);
|
||||
|
||||
let mut scrape_requests = create_scrape_requests(rng, &info_hashes);
|
||||
|
||||
let time = Time(Instant::now());
|
||||
|
||||
for (request, src) in scrape_requests.iter() {
|
||||
let key = ConnectionKey {
|
||||
connection_id: request.connection_id,
|
||||
socket_addr: *src,
|
||||
};
|
||||
|
||||
state.connections.insert(key, time);
|
||||
}
|
||||
|
||||
let mut scrape_requests = requests;
|
||||
let scrape_requests = scrape_requests.drain(..);
|
||||
|
||||
::std::thread::sleep(Duration::from_millis(100));
|
||||
|
||||
let now = Instant::now();
|
||||
|
||||
println!("running benchmark..");
|
||||
|
|
@ -57,18 +38,18 @@ pub fn bench(
|
|||
let requests_per_second = SCRAPE_REQUESTS as f64 / (duration.as_millis() as f64 / 1000.0);
|
||||
let time_per_request = duration.as_nanos() as f64 / SCRAPE_REQUESTS as f64;
|
||||
|
||||
println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
println!("time per request: {:.2}ns", time_per_request);
|
||||
// println!("\nrequests/second: {:.2}", requests_per_second);
|
||||
// println!("time per request: {:.2}ns", time_per_request);
|
||||
|
||||
let mut total_num_peers = 0.0f64;
|
||||
// let mut total_num_peers = 0.0f64;
|
||||
let mut num_responses: usize = 0;
|
||||
|
||||
for (response, _src) in responses.drain(..){
|
||||
if let Response::Scrape(response) = response {
|
||||
for stats in response.torrent_stats {
|
||||
total_num_peers += f64::from(stats.seeders.0);
|
||||
total_num_peers += f64::from(stats.leechers.0);
|
||||
}
|
||||
if let Response::Scrape(_response) = response {
|
||||
// for stats in response.torrent_stats {
|
||||
// total_num_peers += f64::from(stats.seeders.0);
|
||||
// total_num_peers += f64::from(stats.leechers.0);
|
||||
// }
|
||||
|
||||
num_responses += 1;
|
||||
}
|
||||
|
|
@ -78,13 +59,13 @@ pub fn bench(
|
|||
println!("ERROR: only {} responses received", num_responses);
|
||||
}
|
||||
|
||||
println!("avg num peers reported: {:.2}", total_num_peers / (SCRAPE_REQUESTS as f64 * SCRAPE_NUM_HASHES as f64));
|
||||
// println!("avg num peers reported: {:.2}", total_num_peers / (SCRAPE_REQUESTS as f64 * SCRAPE_NUM_HASHES as f64));
|
||||
|
||||
(requests_per_second, time_per_request)
|
||||
}
|
||||
|
||||
|
||||
fn create_scrape_requests(
|
||||
pub fn create_requests(
|
||||
rng: &mut impl Rng,
|
||||
info_hashes: &Vec<InfoHash>
|
||||
) -> Vec<(ScrapeRequest, SocketAddr)> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue