diff --git a/aquatic_http_load_test/src/config.rs b/aquatic_http_load_test/src/config.rs index 63cd124..bf23557 100644 --- a/aquatic_http_load_test/src/config.rs +++ b/aquatic_http_load_test/src/config.rs @@ -8,84 +8,40 @@ use serde::{Serialize, Deserialize}; pub struct Config { /// Server address pub server_address: SocketAddr, - /// Number of sockets and socket worker threads - /// - /// Sockets will bind to one port each, and with - /// multiple_client_ips = true, additionally to one IP each. - pub num_socket_workers: u8, - /// Number of workers generating requests from responses, as well as - /// requests not connected to previous ones. - pub num_request_workers: usize, - /// Run duration (quit and generate report after this many seconds) + pub num_workers: u8, pub duration: usize, pub network: NetworkConfig, - pub handler: HandlerConfig, + pub torrents: TorrentConfig, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] pub struct NetworkConfig { - /// True means bind to one localhost IP per socket. On macOS, this by - /// default causes all server responses to go to one socket worker. - /// Default option ("true") can cause issues on macOS. - /// - /// The point of multiple IPs is to possibly cause a better distribution - /// of requests to servers with SO_REUSEPORT option. - pub multiple_client_ips: bool, - /// Use Ipv6 only - pub ipv6_client: bool, - /// Number of first client port - pub first_port: u16, - /// Socket worker poll timeout in microseconds - pub poll_timeout: u64, - /// Socket worker polling event number + pub poll_timeout_microseconds: u64, pub poll_event_capacity: usize, - /// Size of socket recv buffer. Use 0 for OS default. - /// - /// This setting can have a big impact on dropped packages. It might - /// require changing system defaults. Some examples of commands to set - /// recommended values for different operating systems: - /// - /// macOS: - /// $ sudo sysctl net.inet.udp.recvspace=6000000 - /// $ sudo sysctl net.inet.udp.maxdgram=500000 # Not necessary, but recommended - /// $ sudo sysctl kern.ipc.maxsockbuf=8388608 # Not necessary, but recommended - /// - /// Linux: - /// $ sudo sysctl -w net.core.rmem_max=104857600 - /// $ sudo sysctl -w net.core.rmem_default=104857600 - pub recv_buffer: usize, } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] -pub struct HandlerConfig { +pub struct TorrentConfig { /// Number of torrents to simulate pub number_of_torrents: usize, /// Maximum number of torrents to ask about in scrape requests pub scrape_max_torrents: usize, - /// Handler: max number of responses to collect for before processing - pub max_responses_per_iter: usize, - /// Probability that a generated request is a announce request, as part - /// of sum of the various weight arguments. - pub weight_announce: usize, - /// Probability that a generated request is a scrape request, as part - /// of sum of the various weight arguments. - pub weight_scrape: usize, - /// Handler: max microseconds to wait for single response from channel - pub channel_timeout: u64, /// Pareto shape /// /// Fake peers choose torrents according to Pareto distribution. pub torrent_selection_pareto_shape: f64, /// Probability that a generated peer is a seeder pub peer_seeder_probability: f64, - /// Part of additional request creation calculation, meaning requests - /// which are not dependent on previous responses from server. Higher - /// means more. - pub additional_request_factor: f64, + /// Probability that a generated request is a announce request, as part + /// of sum of the various weight arguments. + pub weight_announce: usize, + /// Probability that a generated request is a scrape request, as part + /// of sum of the various weight arguments. + pub weight_scrape: usize, } @@ -93,11 +49,10 @@ impl Default for Config { fn default() -> Self { Self { server_address: "127.0.0.1:3000".parse().unwrap(), - num_socket_workers: 1, - num_request_workers: 1, + num_workers: 1, duration: 0, network: NetworkConfig::default(), - handler: HandlerConfig::default(), + torrents: TorrentConfig::default(), } } } @@ -105,29 +60,22 @@ impl Default for Config { impl Default for NetworkConfig { fn default() -> Self { Self { - multiple_client_ips: true, - ipv6_client: false, - first_port: 45_000, - poll_timeout: 276, - poll_event_capacity: 2_877, - recv_buffer: 6_000_000, + poll_timeout_microseconds: 20, + poll_event_capacity: 4096, } } } -impl Default for HandlerConfig { +impl Default for TorrentConfig { fn default() -> Self { Self { number_of_torrents: 10_000, peer_seeder_probability: 0.25, scrape_max_torrents: 50, + torrent_selection_pareto_shape: 2.0, weight_announce: 5, weight_scrape: 0, - additional_request_factor: 0.4, - max_responses_per_iter: 10_000, - channel_timeout: 200, - torrent_selection_pareto_shape: 2.0, } } } diff --git a/aquatic_http_load_test/src/main.rs b/aquatic_http_load_test/src/main.rs index 87528f9..d2528d7 100644 --- a/aquatic_http_load_test/src/main.rs +++ b/aquatic_http_load_test/src/main.rs @@ -28,23 +28,23 @@ pub fn main(){ fn run(config: Config) -> ::anyhow::Result<()> { - if config.handler.weight_announce + config.handler.weight_scrape == 0 { + if config.torrents.weight_announce + config.torrents.weight_scrape == 0 { panic!("Error: at least one weight must be larger than zero."); } println!("Starting client with config: {:#?}", config); - let mut info_hashes = Vec::with_capacity(config.handler.number_of_torrents); + let mut info_hashes = Vec::with_capacity(config.torrents.number_of_torrents); let mut rng = SmallRng::from_entropy(); - for _ in 0..config.handler.number_of_torrents { + for _ in 0..config.torrents.number_of_torrents { info_hashes.push(InfoHash(rng.gen())); } let pareto = Pareto::new( 1.0, - config.handler.torrent_selection_pareto_shape + config.torrents.torrent_selection_pareto_shape ).unwrap(); let state = LoadTestState { @@ -55,7 +55,7 @@ fn run(config: Config) -> ::anyhow::Result<()> { // Start socket workers - for _ in 0..config.num_socket_workers { + for _ in 0..config.num_workers { let config = config.clone(); let state = state.clone(); diff --git a/aquatic_http_load_test/src/network.rs b/aquatic_http_load_test/src/network.rs index 51f6dd2..e502675 100644 --- a/aquatic_http_load_test/src/network.rs +++ b/aquatic_http_load_test/src/network.rs @@ -11,7 +11,6 @@ use crate::config::*; use crate::utils::create_random_request; - pub struct Connection { stream: TcpStream, read_buffer: [u8; 2048], @@ -154,7 +153,7 @@ pub fn run_socket_thread( state: LoadTestState, num_initial_requests: usize, ) { - let timeout = Duration::from_micros(config.network.poll_timeout); + let timeout = Duration::from_micros(config.network.poll_timeout_microseconds); let mut connections: ConnectionMap = HashMap::new(); let mut poll = Poll::new().expect("create poll"); diff --git a/aquatic_http_load_test/src/utils.rs b/aquatic_http_load_test/src/utils.rs index 0f1d5da..c4874f1 100644 --- a/aquatic_http_load_test/src/utils.rs +++ b/aquatic_http_load_test/src/utils.rs @@ -14,8 +14,8 @@ pub fn create_random_request( rng: &mut impl Rng, ) -> Request { let weights = vec![ - config.handler.weight_announce as u32, - config.handler.weight_scrape as u32, + config.torrents.weight_announce as u32, + config.torrents.weight_scrape as u32, ]; let items = vec![ @@ -47,7 +47,7 @@ fn create_announce_request( rng: &mut impl Rng, ) -> Request { let (event, bytes_left) = { - if rng.gen_bool(config.handler.peer_seeder_probability) { + if rng.gen_bool(config.torrents.peer_seeder_probability) { (AnnounceEvent::Completed, 0) } else { (AnnounceEvent::Started, 50) @@ -93,7 +93,7 @@ fn select_info_hash_index( state: &LoadTestState, rng: &mut impl Rng, ) -> usize { - pareto_usize(rng, &state.pareto, config.handler.number_of_torrents - 1) + pareto_usize(rng, &state.pareto, config.torrents.number_of_torrents - 1) }