mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-04-02 18:55:32 +00:00
start work on using seperate threads for sockets and handlers
This commit is contained in:
parent
8d7cbb7926
commit
3527952242
12 changed files with 180 additions and 98 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
|
@ -30,6 +30,8 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bittorrent_udp",
|
"bittorrent_udp",
|
||||||
"cli_helpers",
|
"cli_helpers",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"histogram",
|
"histogram",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
|
|
@ -222,6 +224,27 @@ dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dashmap"
|
name = "dashmap"
|
||||||
version = "3.10.0"
|
version = "3.10.0"
|
||||||
|
|
|
||||||
1
TODO.md
1
TODO.md
|
|
@ -5,6 +5,7 @@
|
||||||
* Generic bench function since current functions are almost identical
|
* Generic bench function since current functions are almost identical
|
||||||
* Show percentile stats for peers per torrent
|
* Show percentile stats for peers per torrent
|
||||||
* aquatic
|
* aquatic
|
||||||
|
* https://docs.rs/crossbeam/0.7.3/crossbeam/utils/struct.Backoff.html#method.is_completed
|
||||||
* Tests
|
* Tests
|
||||||
* Handle Ipv4 and Ipv6 peers. Probably split state. Ipv4 peers can't make
|
* Handle Ipv4 and Ipv6 peers. Probably split state. Ipv4 peers can't make
|
||||||
use of Ipv6 ones. Ipv6 ones may or may note be able to make use of Ipv4
|
use of Ipv6 ones. Ipv6 ones may or may note be able to make use of Ipv4
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ name = "aquatic"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bittorrent_udp = { path = "../bittorrent_udp" }
|
bittorrent_udp = { path = "../bittorrent_udp" }
|
||||||
cli_helpers = { path = "../cli_helpers" }
|
cli_helpers = { path = "../cli_helpers" }
|
||||||
|
crossbeam-queue = "0.2"
|
||||||
|
crossbeam-utils = "0.7"
|
||||||
dashmap = "3"
|
dashmap = "3"
|
||||||
histogram = "0.6"
|
histogram = "0.6"
|
||||||
indexmap = "1"
|
indexmap = "1"
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@ use std::sync::atomic::AtomicUsize;
|
||||||
use std::net::{SocketAddr, IpAddr};
|
use std::net::{SocketAddr, IpAddr};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
|
use crossbeam_queue::ArrayQueue;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
pub use bittorrent_udp::types::*;
|
pub use bittorrent_udp::types::*;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
|
||||||
|
|
||||||
pub const MAX_PACKET_SIZE: usize = 4096;
|
pub const MAX_PACKET_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
|
@ -137,14 +140,18 @@ pub struct State {
|
||||||
pub connections: Arc<ConnectionMap>,
|
pub connections: Arc<ConnectionMap>,
|
||||||
pub torrents: Arc<TorrentMap>,
|
pub torrents: Arc<TorrentMap>,
|
||||||
pub statistics: Arc<Statistics>,
|
pub statistics: Arc<Statistics>,
|
||||||
|
pub request_queue: Arc<ArrayQueue<(Request, SocketAddr)>>,
|
||||||
|
pub response_queue: Arc<ArrayQueue<(Response, SocketAddr)>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new() -> Self {
|
pub fn new(config: &Config) -> Self {
|
||||||
Self {
|
Self {
|
||||||
connections: Arc::new(DashMap::new()),
|
connections: Arc::new(DashMap::new()),
|
||||||
torrents: Arc::new(DashMap::new()),
|
torrents: Arc::new(DashMap::new()),
|
||||||
statistics: Arc::new(Statistics::default()),
|
statistics: Arc::new(Statistics::default()),
|
||||||
|
request_queue: Arc::new(ArrayQueue::new(config.request_queue_len)),
|
||||||
|
response_queue: Arc::new(ArrayQueue::new(config.response_queue_len)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ use serde::{Serialize, Deserialize};
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Spawn this number of threads for workers
|
/// Spawn this number of threads for workers
|
||||||
pub num_threads: usize,
|
pub socket_workers: usize,
|
||||||
|
pub response_workers: usize,
|
||||||
|
pub request_queue_len: usize,
|
||||||
|
pub response_queue_len: usize,
|
||||||
pub network: NetworkConfig,
|
pub network: NetworkConfig,
|
||||||
pub statistics: StatisticsConfig,
|
pub statistics: StatisticsConfig,
|
||||||
pub cleaning: CleaningConfig,
|
pub cleaning: CleaningConfig,
|
||||||
|
|
@ -50,7 +53,10 @@ pub struct CleaningConfig {
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
num_threads: 4,
|
socket_workers: 1,
|
||||||
|
response_workers: 1,
|
||||||
|
request_queue_len: 4096,
|
||||||
|
response_queue_len: 4096 * 4,
|
||||||
network: NetworkConfig::default(),
|
network: NetworkConfig::default(),
|
||||||
statistics: StatisticsConfig::default(),
|
statistics: StatisticsConfig::default(),
|
||||||
cleaning: CleaningConfig::default(),
|
cleaning: CleaningConfig::default(),
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ use std::sync::atomic::Ordering;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use std::vec::Drain;
|
use std::vec::Drain;
|
||||||
|
|
||||||
use rand::{Rng, rngs::{SmallRng, StdRng}};
|
use rand::{SeedableRng, Rng, rngs::{SmallRng, StdRng}};
|
||||||
|
use crossbeam_utils::Backoff;
|
||||||
|
|
||||||
use bittorrent_udp::types::*;
|
use bittorrent_udp::types::*;
|
||||||
|
|
||||||
|
|
@ -11,16 +12,66 @@ use crate::common::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn handle(
|
||||||
|
state: State,
|
||||||
|
config: Config,
|
||||||
|
){
|
||||||
|
let mut connect_requests: Vec<(ConnectRequest, SocketAddr)> = Vec::new();
|
||||||
|
let mut announce_requests: Vec<(AnnounceRequest, SocketAddr)> = Vec::new();
|
||||||
|
let mut scrape_requests: Vec<(ScrapeRequest, SocketAddr)> = Vec::new();
|
||||||
|
|
||||||
|
let mut std_rng = StdRng::from_entropy();
|
||||||
|
let mut small_rng = SmallRng::from_rng(&mut std_rng).unwrap();
|
||||||
|
|
||||||
|
let backoff = Backoff::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if state.request_queue.is_empty(){
|
||||||
|
backoff.snooze();
|
||||||
|
} else {
|
||||||
|
while let Ok((request, src)) = state.request_queue.pop(){
|
||||||
|
match request {
|
||||||
|
Request::Connect(r) => {
|
||||||
|
connect_requests.push((r, src))
|
||||||
|
},
|
||||||
|
Request::Announce(r) => {
|
||||||
|
announce_requests.push((r, src))
|
||||||
|
},
|
||||||
|
Request::Scrape(r) => {
|
||||||
|
scrape_requests.push((r, src))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_connect_requests(
|
||||||
|
&state,
|
||||||
|
&mut std_rng,
|
||||||
|
connect_requests.drain(..)
|
||||||
|
);
|
||||||
|
handle_announce_requests(
|
||||||
|
&state,
|
||||||
|
&config,
|
||||||
|
&mut small_rng,
|
||||||
|
announce_requests.drain(..),
|
||||||
|
);
|
||||||
|
handle_scrape_requests(
|
||||||
|
&state,
|
||||||
|
scrape_requests.drain(..),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn handle_connect_requests(
|
pub fn handle_connect_requests(
|
||||||
state: &State,
|
state: &State,
|
||||||
rng: &mut StdRng,
|
rng: &mut StdRng,
|
||||||
responses: &mut Vec<(Response, SocketAddr)>,
|
|
||||||
requests: Drain<(ConnectRequest, SocketAddr)>,
|
requests: Drain<(ConnectRequest, SocketAddr)>,
|
||||||
){
|
){
|
||||||
let now = Time(Instant::now());
|
let now = Time(Instant::now());
|
||||||
|
|
||||||
responses.extend(requests.map(|(request, src)| {
|
for (request, src) in requests {
|
||||||
let connection_id = ConnectionId(rng.gen());
|
let connection_id = ConnectionId(rng.gen());
|
||||||
|
|
||||||
let key = ConnectionKey {
|
let key = ConnectionKey {
|
||||||
|
|
@ -37,8 +88,10 @@ pub fn handle_connect_requests(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
(response, src)
|
if let Err(err) = state.response_queue.push((response, src)){
|
||||||
}));
|
eprintln!("couldn't push to response queue: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,20 +100,23 @@ pub fn handle_announce_requests(
|
||||||
state: &State,
|
state: &State,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
rng: &mut SmallRng,
|
rng: &mut SmallRng,
|
||||||
responses: &mut Vec<(Response, SocketAddr)>,
|
|
||||||
requests: Drain<(AnnounceRequest, SocketAddr)>,
|
requests: Drain<(AnnounceRequest, SocketAddr)>,
|
||||||
){
|
){
|
||||||
responses.extend(requests.map(|(request, src)| {
|
for (request, src) in requests {
|
||||||
let connection_key = ConnectionKey {
|
let connection_key = ConnectionKey {
|
||||||
connection_id: request.connection_id,
|
connection_id: request.connection_id,
|
||||||
socket_addr: src,
|
socket_addr: src,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !state.connections.contains_key(&connection_key){
|
if !state.connections.contains_key(&connection_key){
|
||||||
return ((ErrorResponse {
|
let response = ErrorResponse {
|
||||||
transaction_id: request.transaction_id,
|
transaction_id: request.transaction_id,
|
||||||
message: "Connection invalid or expired".to_string()
|
message: "Connection invalid or expired".to_string()
|
||||||
}).into(), src);
|
};
|
||||||
|
|
||||||
|
if let Err(err) = state.response_queue.push((response.into(), src)){
|
||||||
|
eprintln!("couldn't push to response queue: {}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let peer_key = PeerMapKey {
|
let peer_key = PeerMapKey {
|
||||||
|
|
@ -124,30 +180,35 @@ pub fn handle_announce_requests(
|
||||||
peers: response_peers
|
peers: response_peers
|
||||||
});
|
});
|
||||||
|
|
||||||
(response, src)
|
if let Err(err) = state.response_queue.push((response, src)){
|
||||||
}));
|
eprintln!("couldn't push to response queue: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn handle_scrape_requests(
|
pub fn handle_scrape_requests(
|
||||||
state: &State,
|
state: &State,
|
||||||
responses: &mut Vec<(Response, SocketAddr)>,
|
|
||||||
requests: Drain<(ScrapeRequest, SocketAddr)>,
|
requests: Drain<(ScrapeRequest, SocketAddr)>,
|
||||||
){
|
){
|
||||||
let empty_stats = create_torrent_scrape_statistics(0, 0);
|
let empty_stats = create_torrent_scrape_statistics(0, 0);
|
||||||
|
|
||||||
responses.extend(requests.map(|(request, src)| {
|
for (request, src) in requests {
|
||||||
let connection_key = ConnectionKey {
|
let connection_key = ConnectionKey {
|
||||||
connection_id: request.connection_id,
|
connection_id: request.connection_id,
|
||||||
socket_addr: src,
|
socket_addr: src,
|
||||||
};
|
};
|
||||||
|
|
||||||
if !state.connections.contains_key(&connection_key){
|
if !state.connections.contains_key(&connection_key){
|
||||||
return ((ErrorResponse {
|
let response = ErrorResponse {
|
||||||
transaction_id: request.transaction_id,
|
transaction_id: request.transaction_id,
|
||||||
message: "Connection invalid or expired".to_string()
|
message: "Connection invalid or expired".to_string()
|
||||||
}).into(), src);
|
};
|
||||||
|
|
||||||
|
if let Err(err) = state.response_queue.push((response.into(), src)){
|
||||||
|
eprintln!("couldn't push to response queue: {}", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stats: Vec<TorrentScrapeStatistics> = Vec::with_capacity(
|
let mut stats: Vec<TorrentScrapeStatistics> = Vec::with_capacity(
|
||||||
|
|
@ -170,8 +231,10 @@ pub fn handle_scrape_requests(
|
||||||
torrent_stats: stats,
|
torrent_stats: stats,
|
||||||
});
|
});
|
||||||
|
|
||||||
(response, src)
|
if let Err(err) = state.response_queue.push((response, src)){
|
||||||
}));
|
eprintln!("couldn't push to response queue: {}", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,18 @@ use common::State;
|
||||||
|
|
||||||
|
|
||||||
pub fn run(config: Config){
|
pub fn run(config: Config){
|
||||||
let state = State::new();
|
let state = State::new(&config);
|
||||||
|
|
||||||
for i in 0..config.num_threads {
|
for _ in 0..config.response_workers {
|
||||||
|
let state = state.clone();
|
||||||
|
let config = config.clone();
|
||||||
|
|
||||||
|
::std::thread::spawn(move || {
|
||||||
|
handlers::handle(state, config);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..config.socket_workers {
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,17 @@
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::net::SocketAddr;
|
|
||||||
use std::io::{Cursor, ErrorKind};
|
use std::io::{Cursor, ErrorKind};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use mio::{Events, Poll, Interest, Token};
|
use mio::{Events, Poll, Interest, Token};
|
||||||
use mio::net::UdpSocket;
|
use mio::net::UdpSocket;
|
||||||
use net2::{UdpSocketExt, UdpBuilder};
|
use net2::{UdpSocketExt, UdpBuilder};
|
||||||
use net2::unix::UnixUdpBuilderExt;
|
use net2::unix::UnixUdpBuilderExt;
|
||||||
use rand::{SeedableRng, rngs::{SmallRng, StdRng}};
|
|
||||||
|
|
||||||
use bittorrent_udp::types::IpVersion;
|
use bittorrent_udp::types::IpVersion;
|
||||||
use bittorrent_udp::converters::{response_to_bytes, request_from_bytes};
|
use bittorrent_udp::converters::{response_to_bytes, request_from_bytes};
|
||||||
|
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::handlers::*;
|
|
||||||
|
|
||||||
|
|
||||||
pub fn run_event_loop(
|
pub fn run_event_loop(
|
||||||
|
|
@ -34,16 +32,10 @@ pub fn run_event_loop(
|
||||||
|
|
||||||
let mut events = Events::with_capacity(config.network.poll_event_capacity);
|
let mut events = Events::with_capacity(config.network.poll_event_capacity);
|
||||||
|
|
||||||
let mut connect_requests: Vec<(ConnectRequest, SocketAddr)> = Vec::new();
|
let timeout = Duration::from_millis(1);
|
||||||
let mut announce_requests: Vec<(AnnounceRequest, SocketAddr)> = Vec::new();
|
|
||||||
let mut scrape_requests: Vec<(ScrapeRequest, SocketAddr)> = Vec::new();
|
|
||||||
let mut responses: Vec<(Response, SocketAddr)> = Vec::new();
|
|
||||||
|
|
||||||
let mut std_rng = StdRng::from_entropy();
|
|
||||||
let mut small_rng = SmallRng::from_rng(&mut std_rng).unwrap();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
poll.poll(&mut events, None)
|
poll.poll(&mut events, Some(timeout))
|
||||||
.expect("failed polling");
|
.expect("failed polling");
|
||||||
|
|
||||||
for event in events.iter(){
|
for event in events.iter(){
|
||||||
|
|
@ -51,17 +43,11 @@ pub fn run_event_loop(
|
||||||
|
|
||||||
if token.0 == token_num {
|
if token.0 == token_num {
|
||||||
if event.is_readable(){
|
if event.is_readable(){
|
||||||
handle_readable_socket(
|
read_requests(
|
||||||
&state,
|
&state,
|
||||||
&config,
|
&config,
|
||||||
&mut socket,
|
&mut socket,
|
||||||
&mut std_rng,
|
|
||||||
&mut small_rng,
|
|
||||||
&mut buffer,
|
&mut buffer,
|
||||||
&mut responses,
|
|
||||||
&mut connect_requests,
|
|
||||||
&mut announce_requests,
|
|
||||||
&mut scrape_requests
|
|
||||||
);
|
);
|
||||||
|
|
||||||
state.statistics.readable_events.fetch_add(1, Ordering::SeqCst);
|
state.statistics.readable_events.fetch_add(1, Ordering::SeqCst);
|
||||||
|
|
@ -72,6 +58,13 @@ pub fn run_event_loop(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
send_responses(
|
||||||
|
&state,
|
||||||
|
&config,
|
||||||
|
&mut socket,
|
||||||
|
&mut buffer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,24 +101,15 @@ fn create_socket(config: &Config) -> ::std::net::UdpSocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Read requests, generate and send back responses
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn handle_readable_socket(
|
fn read_requests(
|
||||||
state: &State,
|
state: &State,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
socket: &mut UdpSocket,
|
socket: &mut UdpSocket,
|
||||||
std_rng: &mut StdRng,
|
|
||||||
small_rng: &mut SmallRng,
|
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
responses: &mut Vec<(Response, SocketAddr)>,
|
|
||||||
connect_requests: &mut Vec<(ConnectRequest, SocketAddr)>,
|
|
||||||
announce_requests: &mut Vec<(AnnounceRequest, SocketAddr)>,
|
|
||||||
scrape_requests: &mut Vec<(ScrapeRequest, SocketAddr)>,
|
|
||||||
){
|
){
|
||||||
let mut requests_received: usize = 0;
|
let mut requests_received: usize = 0;
|
||||||
let mut responses_sent: usize = 0;
|
|
||||||
let mut bytes_received: usize = 0;
|
let mut bytes_received: usize = 0;
|
||||||
let mut bytes_sent: usize = 0;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match socket.recv_from(&mut buffer[..]) {
|
match socket.recv_from(&mut buffer[..]) {
|
||||||
|
|
@ -142,14 +126,12 @@ fn handle_readable_socket(
|
||||||
}
|
}
|
||||||
|
|
||||||
match request {
|
match request {
|
||||||
Ok(Request::Connect(r)) => {
|
Ok(request) => {
|
||||||
connect_requests.push((r, src));
|
let res = state.request_queue.push((request, src));
|
||||||
},
|
|
||||||
Ok(Request::Announce(r)) => {
|
if let Err(err) = res {
|
||||||
announce_requests.push((r, src));
|
eprintln!("couldn't push request to queue: {}", err);
|
||||||
},
|
}
|
||||||
Ok(Request::Scrape(r)) => {
|
|
||||||
scrape_requests.push((r, src));
|
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
eprintln!("request_from_bytes error: {:?}", err);
|
eprintln!("request_from_bytes error: {:?}", err);
|
||||||
|
|
@ -169,7 +151,7 @@ fn handle_readable_socket(
|
||||||
message,
|
message,
|
||||||
};
|
};
|
||||||
|
|
||||||
responses.push((response.into(), src));
|
// responses.push((response.into(), src)); // FIXME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -185,28 +167,28 @@ fn handle_readable_socket(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_connect_requests(
|
if config.statistics.interval != 0 {
|
||||||
state,
|
state.statistics.requests_received
|
||||||
std_rng,
|
.fetch_add(requests_received, Ordering::SeqCst);
|
||||||
responses,
|
state.statistics.bytes_received
|
||||||
connect_requests.drain(..)
|
.fetch_add(bytes_received, Ordering::SeqCst);
|
||||||
);
|
}
|
||||||
handle_announce_requests(
|
}
|
||||||
state,
|
|
||||||
config,
|
|
||||||
small_rng,
|
#[inline]
|
||||||
responses,
|
fn send_responses(
|
||||||
announce_requests.drain(..),
|
state: &State,
|
||||||
);
|
config: &Config,
|
||||||
handle_scrape_requests(
|
socket: &mut UdpSocket,
|
||||||
state,
|
buffer: &mut [u8],
|
||||||
responses,
|
){
|
||||||
scrape_requests.drain(..),
|
let mut responses_sent: usize = 0;
|
||||||
);
|
let mut bytes_sent: usize = 0;
|
||||||
|
|
||||||
let mut cursor = Cursor::new(buffer);
|
let mut cursor = Cursor::new(buffer);
|
||||||
|
|
||||||
for (response, src) in responses.drain(..) {
|
while let Ok((response, src)) = state.response_queue.pop(){
|
||||||
cursor.set_position(0);
|
cursor.set_position(0);
|
||||||
|
|
||||||
response_to_bytes(&mut cursor, response, IpVersion::IPv4).unwrap();
|
response_to_bytes(&mut cursor, response, IpVersion::IPv4).unwrap();
|
||||||
|
|
@ -229,12 +211,8 @@ fn handle_readable_socket(
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.statistics.interval != 0 {
|
if config.statistics.interval != 0 {
|
||||||
state.statistics.requests_received
|
|
||||||
.fetch_add(requests_received, Ordering::SeqCst);
|
|
||||||
state.statistics.responses_sent
|
state.statistics.responses_sent
|
||||||
.fetch_add(responses_sent, Ordering::SeqCst);
|
.fetch_add(responses_sent, Ordering::SeqCst);
|
||||||
state.statistics.bytes_received
|
|
||||||
.fetch_add(bytes_received, Ordering::SeqCst);
|
|
||||||
state.statistics.bytes_sent
|
state.statistics.bytes_sent
|
||||||
.fetch_add(bytes_sent, Ordering::SeqCst);
|
.fetch_add(bytes_sent, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ pub fn bench(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
||||||
) -> (usize, Duration){
|
) -> (usize, Duration){
|
||||||
let mut responses = Vec::with_capacity(ANNOUNCE_REQUESTS);
|
|
||||||
|
|
||||||
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
||||||
let mut cursor = Cursor::new(buffer.as_mut());
|
let mut cursor = Cursor::new(buffer.as_mut());
|
||||||
let mut num_responses: usize = 0;
|
let mut num_responses: usize = 0;
|
||||||
|
|
@ -50,11 +48,10 @@ pub fn bench(
|
||||||
&state,
|
&state,
|
||||||
config,
|
config,
|
||||||
&mut small_rng,
|
&mut small_rng,
|
||||||
&mut responses,
|
|
||||||
requests,
|
requests,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (response, _) in responses.drain(..) {
|
while let Ok((response, src)) = state.response_queue.pop(){
|
||||||
if let Response::Announce(_) = response {
|
if let Response::Announce(_) = response {
|
||||||
num_responses += 1;
|
num_responses += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ pub fn bench(
|
||||||
state: State,
|
state: State,
|
||||||
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
||||||
) -> (usize, Duration){
|
) -> (usize, Duration){
|
||||||
let mut responses = Vec::with_capacity(ITERATIONS);
|
|
||||||
|
|
||||||
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
||||||
let mut cursor = Cursor::new(buffer.as_mut());
|
let mut cursor = Cursor::new(buffer.as_mut());
|
||||||
let mut num_responses: usize = 0;
|
let mut num_responses: usize = 0;
|
||||||
|
|
@ -42,9 +40,9 @@ pub fn bench(
|
||||||
|
|
||||||
let requests = requests.drain(..);
|
let requests = requests.drain(..);
|
||||||
|
|
||||||
handle_connect_requests(&state, &mut rng, &mut responses, requests);
|
handle_connect_requests(&state, &mut rng, requests);
|
||||||
|
|
||||||
for (response, _) in responses.drain(..){
|
while let Ok((response, _)) = state.response_queue.pop(){
|
||||||
if let Response::Connect(_) = response {
|
if let Response::Connect(_) = response {
|
||||||
num_responses += 1;
|
num_responses += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,8 @@ fn run(bench_config: BenchConfig){
|
||||||
let mut announce_data = (0usize, Duration::new(0, 0));
|
let mut announce_data = (0usize, Duration::new(0, 0));
|
||||||
let mut scrape_data = (0usize, Duration::new(0, 0));
|
let mut scrape_data = (0usize, Duration::new(0, 0));
|
||||||
|
|
||||||
|
let config = Config::default();
|
||||||
|
|
||||||
println!("# Benchmarking request handlers\n");
|
println!("# Benchmarking request handlers\n");
|
||||||
|
|
||||||
// Benchmark connect handler
|
// Benchmark connect handler
|
||||||
|
|
@ -95,7 +97,7 @@ fn run(bench_config: BenchConfig){
|
||||||
let pb = create_progress_bar("Connect handler", bench_config.num_rounds);
|
let pb = create_progress_bar("Connect handler", bench_config.num_rounds);
|
||||||
|
|
||||||
for _ in (0..bench_config.num_rounds).progress_with(pb){
|
for _ in (0..bench_config.num_rounds).progress_with(pb){
|
||||||
let state = State::new();
|
let state = State::new(&config);
|
||||||
|
|
||||||
let handles: Vec<_> = (0..bench_config.num_threads).map(|_| {
|
let handles: Vec<_> = (0..bench_config.num_threads).map(|_| {
|
||||||
let requests = requests.clone();
|
let requests = requests.clone();
|
||||||
|
|
@ -115,7 +117,6 @@ fn run(bench_config: BenchConfig){
|
||||||
|
|
||||||
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
let mut rng = SmallRng::from_rng(thread_rng()).unwrap();
|
||||||
let info_hashes = create_info_hashes(&mut rng);
|
let info_hashes = create_info_hashes(&mut rng);
|
||||||
let config = Config::default();
|
|
||||||
|
|
||||||
// Benchmark announce handler
|
// Benchmark announce handler
|
||||||
let last_torrents: Option<Arc<TorrentMap>> = {
|
let last_torrents: Option<Arc<TorrentMap>> = {
|
||||||
|
|
@ -156,7 +157,7 @@ fn run(bench_config: BenchConfig){
|
||||||
let mut last_torrents = None;
|
let mut last_torrents = None;
|
||||||
|
|
||||||
for i in (0..bench_config.num_rounds).progress_with(pb){
|
for i in (0..bench_config.num_rounds).progress_with(pb){
|
||||||
let mut state = State::new();
|
let mut state = State::new(&config);
|
||||||
|
|
||||||
state.connections = connections.clone();
|
state.connections = connections.clone();
|
||||||
|
|
||||||
|
|
@ -185,7 +186,7 @@ fn run(bench_config: BenchConfig){
|
||||||
|
|
||||||
// Benchmark scrape handler
|
// Benchmark scrape handler
|
||||||
{
|
{
|
||||||
let mut state = State::new();
|
let mut state = State::new(&config);
|
||||||
state.torrents = last_torrents.unwrap();
|
state.torrents = last_torrents.unwrap();
|
||||||
|
|
||||||
let requests = scrape::create_requests(&mut rng, &info_hashes);
|
let requests = scrape::create_requests(&mut rng, &info_hashes);
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ pub fn bench(
|
||||||
state: &State,
|
state: &State,
|
||||||
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
requests: Arc<Vec<([u8; MAX_REQUEST_BYTES], SocketAddr)>>
|
||||||
) -> (usize, Duration){
|
) -> (usize, Duration){
|
||||||
let mut responses = Vec::with_capacity(SCRAPE_REQUESTS);
|
|
||||||
|
|
||||||
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
let mut buffer = [0u8; MAX_PACKET_SIZE];
|
||||||
let mut cursor = Cursor::new(buffer.as_mut());
|
let mut cursor = Cursor::new(buffer.as_mut());
|
||||||
let mut num_responses: usize = 0;
|
let mut num_responses: usize = 0;
|
||||||
|
|
@ -45,11 +43,10 @@ pub fn bench(
|
||||||
|
|
||||||
handle_scrape_requests(
|
handle_scrape_requests(
|
||||||
&state,
|
&state,
|
||||||
&mut responses,
|
|
||||||
requests,
|
requests,
|
||||||
);
|
);
|
||||||
|
|
||||||
for (response, _src) in responses.drain(..){
|
while let Ok((response, _)) = state.response_queue.pop(){
|
||||||
if let Response::Scrape(_) = response {
|
if let Response::Scrape(_) = response {
|
||||||
num_responses += 1;
|
num_responses += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue