diff --git a/tig-benchmarker/Cargo.toml b/tig-benchmarker/Cargo.toml
index 32eb6f9..790650e 100644
--- a/tig-benchmarker/Cargo.toml
+++ b/tig-benchmarker/Cargo.toml
@@ -8,6 +8,7 @@ repository.workspace = true
edition.workspace = true
[dependencies]
+clap = { version = "4.5.4", optional = true }
futures = { version = "0.3.30" }
gloo-timers = { version = "0.3.0", optional = true, features = ["futures"] }
js-sys = { version = "0.3.68", optional = true }
@@ -17,11 +18,13 @@ rand_distr = { version = "0.4.3", default-features = false, features = [
"alloc",
] }
serde = { version = "1.0", features = ["derive"] }
+serde_json = { version = "1.0.113" }
serde-wasm-bindgen = { version = "0.6.5", optional = true }
tig-api = { path = "../tig-api" }
tig-structs = { path = "../tig-structs" }
tig-utils = { path = "../tig-utils" }
tig-worker = { path = "../tig-worker" }
+tokio = { version = "1.37.0", features = ["full"], optional = true }
wasm-bindgen = { version = "0.2.91", features = [
"serde-serialize",
], optional = true }
@@ -33,6 +36,7 @@ crate-type = ["cdylib", "rlib"]
[features]
default = ["browser"]
+standalone = ["dep:clap", "dep:tokio", "tig-api/request"]
browser = [
"dep:gloo-timers",
"dep:wasm-bindgen",
diff --git a/tig-benchmarker/Dockerfile b/tig-benchmarker/Dockerfile
new file mode 100644
index 0000000..b7847c0
--- /dev/null
+++ b/tig-benchmarker/Dockerfile
@@ -0,0 +1,9 @@
+FROM rust:1.77
+
+WORKDIR /app
+COPY . .
+RUN cargo build -p tig-benchmarker --bins --release --no-default-features --features standalone
+RUN cp target/release/tig-benchmarker /usr/local/bin/tig-benchmarker
+RUN chmod +x /usr/local/bin/tig-benchmarker
+
+ENTRYPOINT ["tig-benchmarker"]
\ No newline at end of file
diff --git a/tig-benchmarker/README.md b/tig-benchmarker/README.md
index 13a946b..1ede044 100644
--- a/tig-benchmarker/README.md
+++ b/tig-benchmarker/README.md
@@ -1,10 +1,14 @@
# tig-benchmarker
-A Rust crate that implements a Benchmarker for TIG that can run in the browser.
+A Rust crate that implements a Benchmarker for TIG.
-This browser benchmarker is deployed to https://play.tig.foundation/benchmarker
+## Browser Benchmarker
-To run it locally, run the following commands before visiting localhost in your browser:
+`tig-benchmarker` can be compiled to WASM with bindings for browsers.
+
+The browser version is deployed to https://play.tig.foundation/benchmarker
+
+To build & run it locally, run the following commands before visiting localhost in your browser:
```
# uncomment below to install wasm-pack
@@ -14,7 +18,33 @@ wasm-pack build --release --target web
python3 -m http.server 80
```
-See `tig-api` [README](../tig-api/README.md) for API Urls.
+## Standalone Benchmarker
+
+`tig-benchmarker` can be compiled into an executable for running locally.
+
+There are two ways to run locally:
+
+1. Compile into exectuable and then run the executable:
+ ```
+ cargo build -p tig-benchmarker --release --no-default-features --features standalone
+ # edit below line for your own algorithm selection
+ echo '{"satisfiability":"schnoing","vehicle_routing":"clarke_wright","knapsack":"dynamic"}' >> algo_selection.json
+ ./target/release/tig-benchmarker
algo_selection.json
+ ```
+
+2. Compile executable in a docker, and run the docker:
+ ```
+ docker build -f tig-benchmarker/Dockerfile -t tig-benchmarker .
+ # edit below line for your own algorithm selection
+ echo '{"satisfiability":"schnoing","vehicle_routing":"clarke_wright","knapsack":"dynamic"}' >> algo_selection.json
+ docker run -it -v $(pwd):/app tig-benchmarker algo_selection.json
+ ```
+
+**Note:**
+
+* Every 10 seconds, the benchmarker reads your json file path and uses the contents to update its algorithm selection.
+* You can see available algorithms in the dropdowns of the [Benchmarker UI](https://play.tig.foundation/benchmarker)
+* `tig-benchmarker` can be executed with `--help` to see all options including setting the number of workers, and setting the duration of a benchmark
# Finding your API Key
@@ -36,4 +66,4 @@ See `tig-api` [README](../tig-api/README.md) for API Urls.
# License
-[End User License Agreement](../docs/agreements/end_user_license_agreement.pdf)
\ No newline at end of file
+[End User License Agreement](../docs/agreements/end_user_license_agreement.pdf)
diff --git a/tig-benchmarker/src/main.rs b/tig-benchmarker/src/main.rs
new file mode 100644
index 0000000..5597b9a
--- /dev/null
+++ b/tig-benchmarker/src/main.rs
@@ -0,0 +1,78 @@
+// #[cfg(any(not(feature = "standalone"), feature = "browser"))]
+// compile_error!("to build the binary use `--no-default-features --features standalone`");
+
+mod benchmarker;
+mod future_utils;
+use clap::{value_parser, Arg, Command};
+use std::{collections::HashMap, fs, path::PathBuf};
+
+fn cli() -> Command {
+ Command::new("TIG Benchmarker")
+ .about("Standalone benchmarker")
+ .arg_required_else_help(true)
+ .arg(
+ Arg::new("PLAYER_ID")
+ .help("Your wallet address")
+ .required(true)
+ .value_parser(value_parser!(String)),
+ )
+ .arg(
+ Arg::new("API_KEY")
+ .help("Your API Key")
+ .required(true)
+ .value_parser(value_parser!(String)),
+ )
+ .arg(
+ Arg::new("ALGORITHMS_SELECTION")
+ .help("Path to json file with your algorithm selection")
+ .required(true)
+ .value_parser(value_parser!(PathBuf)),
+ )
+ .arg(
+ Arg::new("workers")
+ .long("workers")
+ .help("(Optional) Set number of workers")
+ .default_value("4")
+ .value_parser(value_parser!(u32)),
+ )
+ .arg(
+ Arg::new("duration")
+ .long("duration")
+ .help("(Optional) Set duration of a benchmark in milliseconds")
+ .default_value("15000")
+ .value_parser(value_parser!(u32)),
+ )
+ .arg(
+ Arg::new("api")
+ .long("api")
+ .help("(Optional) Set api_url")
+ .default_value("https://api.tig.foundation/play")
+ .value_parser(value_parser!(String)),
+ )
+}
+
+#[tokio::main]
+async fn main() {
+ let matches = cli().get_matches();
+
+ let algorithms_path = matches.get_one::("ALGORITHMS_SELECTION").unwrap();
+ let num_workers = *matches.get_one::("workers").unwrap();
+ let duration = *matches.get_one::("duration").unwrap();
+ benchmarker::setup(
+ matches.get_one::("api").unwrap().clone(),
+ matches.get_one::("API_KEY").unwrap().clone(),
+ matches.get_one::("PLAYER_ID").unwrap().clone(),
+ )
+ .await;
+ benchmarker::start(num_workers, duration).await;
+ loop {
+ let selection = serde_json::from_str::>(
+ &fs::read_to_string(algorithms_path).unwrap(),
+ )
+ .unwrap();
+ for (challenge_id, algorithm_id) in selection {
+ benchmarker::select_algorithm(challenge_id, algorithm_id).await;
+ }
+ future_utils::sleep(10000).await;
+ }
+}