WIP: aquatic_http_load_test: clean up config structs

This commit is contained in:
Joakim Frostegård 2020-07-20 15:08:33 +02:00
parent da3b2bcd8c
commit ff6eddfc85
4 changed files with 26 additions and 79 deletions

View file

@ -8,84 +8,40 @@ use serde::{Serialize, Deserialize};
pub struct Config { pub struct Config {
/// Server address /// Server address
pub server_address: SocketAddr, pub server_address: SocketAddr,
/// Number of sockets and socket worker threads pub num_workers: u8,
///
/// 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 duration: usize, pub duration: usize,
pub network: NetworkConfig, pub network: NetworkConfig,
pub handler: HandlerConfig, pub torrents: TorrentConfig,
} }
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct NetworkConfig { pub struct NetworkConfig {
/// True means bind to one localhost IP per socket. On macOS, this by pub poll_timeout_microseconds: u64,
/// 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_event_capacity: usize, 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)] #[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default)] #[serde(default)]
pub struct HandlerConfig { pub struct TorrentConfig {
/// Number of torrents to simulate /// Number of torrents to simulate
pub number_of_torrents: usize, pub number_of_torrents: usize,
/// Maximum number of torrents to ask about in scrape requests /// Maximum number of torrents to ask about in scrape requests
pub scrape_max_torrents: usize, 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 /// Pareto shape
/// ///
/// Fake peers choose torrents according to Pareto distribution. /// Fake peers choose torrents according to Pareto distribution.
pub torrent_selection_pareto_shape: f64, pub torrent_selection_pareto_shape: f64,
/// Probability that a generated peer is a seeder /// Probability that a generated peer is a seeder
pub peer_seeder_probability: f64, pub peer_seeder_probability: f64,
/// Part of additional request creation calculation, meaning requests /// Probability that a generated request is a announce request, as part
/// which are not dependent on previous responses from server. Higher /// of sum of the various weight arguments.
/// means more. pub weight_announce: usize,
pub additional_request_factor: f64, /// 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 { fn default() -> Self {
Self { Self {
server_address: "127.0.0.1:3000".parse().unwrap(), server_address: "127.0.0.1:3000".parse().unwrap(),
num_socket_workers: 1, num_workers: 1,
num_request_workers: 1,
duration: 0, duration: 0,
network: NetworkConfig::default(), network: NetworkConfig::default(),
handler: HandlerConfig::default(), torrents: TorrentConfig::default(),
} }
} }
} }
@ -105,29 +60,22 @@ impl Default for Config {
impl Default for NetworkConfig { impl Default for NetworkConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
multiple_client_ips: true, poll_timeout_microseconds: 20,
ipv6_client: false, poll_event_capacity: 4096,
first_port: 45_000,
poll_timeout: 276,
poll_event_capacity: 2_877,
recv_buffer: 6_000_000,
} }
} }
} }
impl Default for HandlerConfig { impl Default for TorrentConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
number_of_torrents: 10_000, number_of_torrents: 10_000,
peer_seeder_probability: 0.25, peer_seeder_probability: 0.25,
scrape_max_torrents: 50, scrape_max_torrents: 50,
torrent_selection_pareto_shape: 2.0,
weight_announce: 5, weight_announce: 5,
weight_scrape: 0, weight_scrape: 0,
additional_request_factor: 0.4,
max_responses_per_iter: 10_000,
channel_timeout: 200,
torrent_selection_pareto_shape: 2.0,
} }
} }
} }

View file

@ -28,23 +28,23 @@ pub fn main(){
fn run(config: Config) -> ::anyhow::Result<()> { 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."); panic!("Error: at least one weight must be larger than zero.");
} }
println!("Starting client with config: {:#?}", config); 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(); 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())); info_hashes.push(InfoHash(rng.gen()));
} }
let pareto = Pareto::new( let pareto = Pareto::new(
1.0, 1.0,
config.handler.torrent_selection_pareto_shape config.torrents.torrent_selection_pareto_shape
).unwrap(); ).unwrap();
let state = LoadTestState { let state = LoadTestState {
@ -55,7 +55,7 @@ fn run(config: Config) -> ::anyhow::Result<()> {
// Start socket workers // Start socket workers
for _ in 0..config.num_socket_workers { for _ in 0..config.num_workers {
let config = config.clone(); let config = config.clone();
let state = state.clone(); let state = state.clone();

View file

@ -11,7 +11,6 @@ use crate::config::*;
use crate::utils::create_random_request; use crate::utils::create_random_request;
pub struct Connection { pub struct Connection {
stream: TcpStream, stream: TcpStream,
read_buffer: [u8; 2048], read_buffer: [u8; 2048],
@ -154,7 +153,7 @@ pub fn run_socket_thread(
state: LoadTestState, state: LoadTestState,
num_initial_requests: usize, 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 connections: ConnectionMap = HashMap::new();
let mut poll = Poll::new().expect("create poll"); let mut poll = Poll::new().expect("create poll");

View file

@ -14,8 +14,8 @@ pub fn create_random_request(
rng: &mut impl Rng, rng: &mut impl Rng,
) -> Request { ) -> Request {
let weights = vec![ let weights = vec![
config.handler.weight_announce as u32, config.torrents.weight_announce as u32,
config.handler.weight_scrape as u32, config.torrents.weight_scrape as u32,
]; ];
let items = vec![ let items = vec![
@ -47,7 +47,7 @@ fn create_announce_request(
rng: &mut impl Rng, rng: &mut impl Rng,
) -> Request { ) -> Request {
let (event, bytes_left) = { 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) (AnnounceEvent::Completed, 0)
} else { } else {
(AnnounceEvent::Started, 50) (AnnounceEvent::Started, 50)
@ -93,7 +93,7 @@ fn select_info_hash_index(
state: &LoadTestState, state: &LoadTestState,
rng: &mut impl Rng, rng: &mut impl Rng,
) -> usize { ) -> usize {
pareto_usize(rng, &state.pareto, config.handler.number_of_torrents - 1) pareto_usize(rng, &state.pareto, config.torrents.number_of_torrents - 1)
} }