diff --git a/Cargo.lock b/Cargo.lock index 5c636065..8b9635ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1341,7 +1341,7 @@ dependencies = [ name = "sky-bench" version = "0.8.0" dependencies = [ - "clap 2.34.0", + "clap 4.0.18", "devtimer", "env_logger", "libstress", diff --git a/sky-bench/Cargo.toml b/sky-bench/Cargo.toml index 8ae5129a..9f6d414f 100644 --- a/sky-bench/Cargo.toml +++ b/sky-bench/Cargo.toml @@ -3,6 +3,7 @@ authors = ["Sayan Nandan "] edition = "2021" name = "sky-bench" version = "0.8.0" +description = "The Skytable benchmark tool can be used to benchmark Skytable installations" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,7 +15,7 @@ skytable = { git = "https://github.com/skytable/client-rust.git", features = [ ] } libstress = { path = "../libstress" } # external deps -clap = { version = "2", features = ["yaml"] } +clap = { version = "4", features = ["derive"] } log = "0.4.17" env_logger = "0.9.1" devtimer = "4.0.1" diff --git a/sky-bench/src/bench/mod.rs b/sky-bench/src/bench/mod.rs index 31fa6f54..79ec3642 100644 --- a/sky-bench/src/bench/mod.rs +++ b/sky-bench/src/bench/mod.rs @@ -32,7 +32,6 @@ use { error::{BResult, Error}, util, }, - clap::ArgMatches, devtimer::SimpleTimer, libstress::utils::{generate_random_byte_vector, ran_bytes}, skytable::{Connection, Element, Query, RespCode}, @@ -180,9 +179,7 @@ fn vec_with_cap(cap: usize) -> BResult> { } /// Run the actual benchmarks -pub fn run_bench(servercfg: &ServerConfig, matches: ArgMatches) -> BResult<()> { - // init bench config - let bench_config = BenchmarkConfig::new(servercfg, matches)?; +pub fn run_bench(servercfg: &ServerConfig, bench_config: BenchmarkConfig) -> BResult<()> { // check if we have enough combinations for the given query count and key size if !util::has_enough_ncr(bench_config.kvsize(), bench_config.query_count()) { return Err(Error::Runtime( @@ -251,9 +248,7 @@ pub fn run_bench(servercfg: &ServerConfig, matches: ArgMatches) -> BResult<()> { binfo!("Finished benchmarks. Cleaning up ..."); let r: Element = misc_connection.run_query(Query::from("drop model default.tmpbench force"))?; if r != Element::RespCode(RespCode::Okay) { - return Err(Error::Runtime( - "failed to clean up after benchmarks".into(), - )); + return Err(Error::Runtime("failed to clean up after benchmarks".into())); } if config::should_output_messages() { diff --git a/sky-bench/src/cli.rs b/sky-bench/src/cli.rs new file mode 100644 index 00000000..34a33e2d --- /dev/null +++ b/sky-bench/src/cli.rs @@ -0,0 +1,78 @@ +use clap::{ArgAction, Parser}; + +const HELP_TEMPLATE: &'static str = r#" +{before-help}{name} {version} +{author-with-newline}{about-with-newline} +{usage-heading} {usage} + +{all-args}{after-help} +"#; + +#[derive(Parser, Debug)] +#[command(author, version, about, long_about=None, disable_help_flag=true, help_template=HELP_TEMPLATE)] +pub struct Cli { + #[arg( + short, + long, + help = "Sets the remote host to connect to", + default_value = "127.0.0.1", + value_name = "HOST" + )] + pub host: String, + + #[arg( + short, + long, + help = "Sets the remote port to connect to", + default_value_t = 2003, + value_name = "PORT" + )] + pub port: u16, + + #[arg( + short = 'c', + long = "connections", + help = "Sets the number of simultaneous clients", + value_name = "COUNT", + default_value_t = 10 + )] + pub connections: usize, + + #[arg( + short = 'r', + long = "runs", + help = "Sets the number of times the entire test should be run", + value_name = "RUNS", + default_value_t = 5 + )] + pub runs: usize, + + #[arg( + short = 's', + long = "kvsize", + help = "Sets the size of the key/value pairs", + value_name = "BYTES", + default_value_t = 3 + )] + pub kvsize: usize, + + #[arg( + short = 'q', + long = "queries", + help = "Sets the number of queries to run", + value_name = "QUERIES", + default_value_t = 100_000 + )] + pub query_count: usize, + + #[arg( + short = 'j', + long = "json", + help = "Sets output type to JSON", + default_value_t = false + )] + pub json: bool, + + #[arg(long, help="Print help information", action=ArgAction::Help)] + pub help: Option, +} diff --git a/sky-bench/src/cli.yml b/sky-bench/src/cli.yml deleted file mode 100644 index 0afc683c..00000000 --- a/sky-bench/src/cli.yml +++ /dev/null @@ -1,72 +0,0 @@ -# -# Created on Tue Nov 03 2020 -# -# This file is a part of Skytable -# Copyright (c) 2020, Sayan Nandan -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -# - -name: Skytable Benchmark Tool -version: 0.8.0 -author: Sayan N. -about: | - The Skytable benchmark tool can be used to benchmark Skytable installations. - If you find any issues, then report one here: https://github.com/skytable/skytable -args: - - connections: - short: c - long: connections - value_name: count - help: Sets the number of simultaneous clients - takes_value: true - - queries: - short: q - long: queries - value_name: number - help: Sets the number of queries to run - takes_value: true - - size: - short: s - long: kvsize - value_name: bytes - help: Sets the size of the key/value pairs - takes_value: true - - json: - required: false - long: json - help: Sets output type to JSON - takes_value: false - - host: - short: h - required: false - long: host - value_name: host - help: Sets the remote host to connect to - takes_value: true - - port: - short: p - required: false - long: port - value_name: port - help: Sets the remote port to connect to - takes_value: true - - runs: - short: r - required: false - long: runs - value_name: runs - takes_value: true - help: Sets the number of times the entire test should be run diff --git a/sky-bench/src/config.rs b/sky-bench/src/config.rs index f8e283a4..1bf64e15 100644 --- a/sky-bench/src/config.rs +++ b/sky-bench/src/config.rs @@ -24,72 +24,20 @@ * */ -use { - crate::error::{BResult, Error}, - crate::util, - clap::ArgMatches, - std::{fmt::Display, str::FromStr}, -}; +use crate::{util, Cli}; static mut OUTPUT_JSON: bool = false; #[derive(Clone)] pub struct ServerConfig { /// host - host: Box, + host: String, /// port port: u16, /// connection count for network pool connections: usize, } -#[inline(always)] -fn try_update>(input: Option, target: &mut T) -> BResult<()> -where - ::Err: Display, -{ - if let Some(input) = input { - let parsed = input - .as_ref() - .parse::() - .map_err(|e| Error::Config(format!("parse error: `{}`", e)))?; - *target = parsed; - } - Ok(()) -} - -impl ServerConfig { - const DEFAULT_HOST: &'static str = "127.0.0.1"; - const DEFAULT_PORT: u16 = 2003; - const DEFAULT_CONNECTIONS: usize = 10; - /// Init the default server config - pub fn new(matches: &ArgMatches) -> BResult { - let mut slf = Self { - host: Self::DEFAULT_HOST.into(), - port: Self::DEFAULT_PORT, - connections: Self::DEFAULT_CONNECTIONS, - }; - slf.try_host(matches.value_of_lossy("host")); - slf.try_port(matches.value_of_lossy("port"))?; - slf.try_connections(matches.value_of_lossy("connections"))?; - Ok(slf) - } - /// Update the host - pub fn try_host>(&mut self, host: Option) { - if let Some(host) = host { - self.host = host.as_ref().into(); - } - } - /// Attempt to update the port - pub fn try_port>(&mut self, port: Option) -> BResult<()> { - try_update(port, &mut self.port) - } - /// Attempt to update the connections - pub fn try_connections>(&mut self, con: Option) -> BResult<()> { - try_update(con, &mut self.connections) - } -} - impl ServerConfig { pub fn host(&self) -> &str { self.host.as_ref() @@ -112,25 +60,6 @@ pub struct BenchmarkConfig { } impl BenchmarkConfig { - const DEFAULT_QUERIES: usize = 100_000; - const DEFAULT_KVSIZE: usize = 3; - const DEFAULT_RUNS: usize = 5; - pub fn new(server: &ServerConfig, matches: ArgMatches) -> BResult { - let mut slf = Self { - server: server.clone(), - queries: Self::DEFAULT_QUERIES, - kvsize: Self::DEFAULT_KVSIZE, - runs: Self::DEFAULT_RUNS, - }; - try_update(matches.value_of_lossy("queries"), &mut slf.queries)?; - try_update(matches.value_of_lossy("size"), &mut slf.kvsize)?; - try_update(matches.value_of_lossy("runs"), &mut slf.runs)?; - util::ensure_main_thread(); - unsafe { - OUTPUT_JSON = matches.is_present("json"); - } - Ok(slf) - } pub fn kvsize(&self) -> usize { self.kvsize } @@ -146,3 +75,28 @@ pub fn should_output_messages() -> bool { util::ensure_main_thread(); unsafe { !OUTPUT_JSON } } + +impl From<(&ServerConfig, &Cli)> for BenchmarkConfig { + fn from(tuple: (&ServerConfig, &Cli)) -> Self { + let (server_config, cli) = tuple; + unsafe { + OUTPUT_JSON = cli.json; + } + BenchmarkConfig { + server: server_config.clone(), + queries: cli.query_count, + kvsize: cli.kvsize, + runs: cli.runs, + } + } +} + +impl From<&Cli> for ServerConfig { + fn from(cli: &Cli) -> Self { + ServerConfig { + connections: cli.connections, + host: cli.host.clone(), + port: cli.port, + } + } +} diff --git a/sky-bench/src/error.rs b/sky-bench/src/error.rs index c2519702..b077e222 100644 --- a/sky-bench/src/error.rs +++ b/sky-bench/src/error.rs @@ -36,8 +36,6 @@ pub type BResult = Result; pub enum Error { /// An error originating from the Skytable client Client(SkyError), - /// An error originating from the benchmark/server configuration - Config(String), /// A runtime error Runtime(String), } @@ -52,7 +50,6 @@ impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Error::Client(e) => write!(f, "client error: {}", e), - Error::Config(e) => write!(f, "config error: {}", e), Error::Runtime(e) => write!(f, "runtime error: {}", e), } } diff --git a/sky-bench/src/main.rs b/sky-bench/src/main.rs index 76ea1b2b..38632ca3 100644 --- a/sky-bench/src/main.rs +++ b/sky-bench/src/main.rs @@ -23,17 +23,18 @@ * along with this program. If not, see . * */ - use { - clap::{load_yaml, App}, - config::ServerConfig, + crate::cli::Cli, + clap::Parser, env_logger::Builder, std::{env, process}, }; + #[macro_use] extern crate log; mod bench; +mod cli; mod config; mod error; mod util; @@ -49,15 +50,14 @@ fn main() { } fn run() -> error::BResult<()> { - // init CLI arg parser - let cli_args = load_yaml!("cli.yml"); - let cli = App::from_yaml(cli_args); - let matches = cli.get_matches(); + // Init CLI arg parser + let cli = &Cli::parse(); - // parse args - let cfg = ServerConfig::new(&matches)?; + // Parse args and initialize configs + let server_config = &cli.into(); + let bench_config = (server_config, cli).into(); - // run our task - bench::run_bench(&cfg, matches)?; - util::cleanup(&cfg) + // Run our task + bench::run_bench(server_config, bench_config)?; + util::cleanup(&server_config) }