mirror of
https://github.com/YGGverse/aquatic.git
synced 2026-03-31 17:55:36 +00:00
WIP: aquatic_http_load_test: clean up config structs
This commit is contained in:
parent
da3b2bcd8c
commit
ff6eddfc85
4 changed files with 26 additions and 79 deletions
|
|
@ -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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue