Add bench-exchange (#3826)
This commit is contained in:
parent
bc17edcda3
commit
2518e95fb0
|
@ -1435,6 +1435,16 @@ dependencies = [
|
||||||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-derive"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.39"
|
version = "0.1.39"
|
||||||
|
@ -2198,6 +2208,35 @@ dependencies = [
|
||||||
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "solana-bench-exchange"
|
||||||
|
version = "0.14.0"
|
||||||
|
dependencies = [
|
||||||
|
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bs58 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"solana 0.14.0",
|
||||||
|
"solana-client 0.14.0",
|
||||||
|
"solana-drone 0.14.0",
|
||||||
|
"solana-exchange-api 0.14.0",
|
||||||
|
"solana-exchange-program 0.14.0",
|
||||||
|
"solana-logger 0.14.0",
|
||||||
|
"solana-metrics 0.14.0",
|
||||||
|
"solana-netutil 0.14.0",
|
||||||
|
"solana-sdk 0.14.0",
|
||||||
|
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana-bench-streamer"
|
name = "solana-bench-streamer"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
@ -3275,6 +3314,23 @@ dependencies = [
|
||||||
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ws"
|
||||||
|
version = "0.7.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ws"
|
name = "ws"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
@ -3477,6 +3533,7 @@ dependencies = [
|
||||||
"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b"
|
"checksum nix 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46f0f3210768d796e8fa79ec70ee6af172dacbe7147f5e69be5240a47778302b"
|
||||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||||
"checksum nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22293d25d3f33a8567cc8a1dc20f40c7eeb761ce83d0fcca059858580790cac3"
|
"checksum nom 4.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22293d25d3f33a8567cc8a1dc20f40c7eeb761ce83d0fcca059858580790cac3"
|
||||||
|
"checksum num-derive 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d9fe8fcafd1b86a37ce8a1cfa15ae504817e0c8c2e7ad42767371461ac1d316d"
|
||||||
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
|
||||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||||
|
@ -3624,6 +3681,7 @@ dependencies = [
|
||||||
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
|
"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
|
"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba"
|
||||||
|
"checksum ws 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "329d3e6dd450a9c5c73024e1047f0be7e24121a68484eb0b5368977bee3cf8c3"
|
||||||
"checksum ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcacc3ba9c1ee43e3fd0846a25489ff22f8906e90775d51b6edbae4b95d71f4"
|
"checksum ws 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcacc3ba9c1ee43e3fd0846a25489ff22f8906e90775d51b6edbae4b95d71f4"
|
||||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||||
"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
"checksum xattr 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
".",
|
".",
|
||||||
|
"bench-exchange",
|
||||||
"bench-streamer",
|
"bench-streamer",
|
||||||
"bench-tps",
|
"bench-tps",
|
||||||
"drone",
|
"drone",
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
[package]
|
||||||
|
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
name = "solana-bench-exchange"
|
||||||
|
version = "0.14.0"
|
||||||
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
homepage = "https://solana.com/"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bs58 = "0.2.0"
|
||||||
|
clap = "2.32.0"
|
||||||
|
bincode = "1.1.2"
|
||||||
|
env_logger = "0.6.0"
|
||||||
|
itertools = "0.8.0"
|
||||||
|
log = "0.4.6"
|
||||||
|
num-traits = "0.2"
|
||||||
|
num-derive = "0.2"
|
||||||
|
rayon = "1.0.3"
|
||||||
|
serde = "1.0.87"
|
||||||
|
serde_derive = "1.0.87"
|
||||||
|
serde_json = "1.0.38"
|
||||||
|
# solana-runtime = { path = "../solana/runtime"}
|
||||||
|
solana = { path = "../core", version = "0.14.0" }
|
||||||
|
solana-client = { path = "../client", version = "0.14.0" }
|
||||||
|
solana-drone = { path = "../drone", version = "0.14.0" }
|
||||||
|
solana-exchange-api = { path = "../instruction-processors/exchange_api", version = "0.14.0" }
|
||||||
|
solana-exchange-program = { path = "../instruction-processors/exchange_program", version = "0.14.0" }
|
||||||
|
solana-logger = { path = "../logger", version = "0.14.0" }
|
||||||
|
solana-metrics = { path = "../metrics", version = "0.14.0" }
|
||||||
|
solana-netutil = { path = "../netutil", version = "0.14.0" }
|
||||||
|
solana-sdk = { path = "../sdk", version = "0.14.0" }
|
||||||
|
ws = "0.7.9"
|
||||||
|
untrusted = "0.6.2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
cuda = ["solana/cuda"]
|
||||||
|
erasure = []
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,173 @@
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg, ArgMatches};
|
||||||
|
use solana_drone::drone::DRONE_PORT;
|
||||||
|
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
||||||
|
use untrusted::Input;
|
||||||
|
|
||||||
|
pub struct Config {
|
||||||
|
pub network_addr: SocketAddr,
|
||||||
|
pub drone_addr: SocketAddr,
|
||||||
|
pub identity: Keypair,
|
||||||
|
pub threads: usize,
|
||||||
|
pub num_nodes: usize,
|
||||||
|
pub duration: Duration,
|
||||||
|
pub trade_delay: u64,
|
||||||
|
pub fund_amount: u64,
|
||||||
|
pub batch_size: usize,
|
||||||
|
pub account_groups: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
network_addr: SocketAddr::from(([127, 0, 0, 1], 8001)),
|
||||||
|
drone_addr: SocketAddr::from(([127, 0, 0, 1], DRONE_PORT)),
|
||||||
|
identity: Keypair::new(),
|
||||||
|
num_nodes: 1,
|
||||||
|
threads: 4,
|
||||||
|
duration: Duration::new(u64::max_value(), 0),
|
||||||
|
trade_delay: 0,
|
||||||
|
fund_amount: 100_000,
|
||||||
|
batch_size: 100,
|
||||||
|
account_groups: 100,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_args<'a, 'b>() -> App<'a, 'b> {
|
||||||
|
App::new(crate_name!())
|
||||||
|
.about(crate_description!())
|
||||||
|
.version(crate_version!())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("network")
|
||||||
|
.short("n")
|
||||||
|
.long("network")
|
||||||
|
.value_name("HOST:PORT")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("127.0.0.1:8001")
|
||||||
|
.help("Network's gossip entry point; defaults to 127.0.0.1:8001"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("drone")
|
||||||
|
.short("d")
|
||||||
|
.long("drone")
|
||||||
|
.value_name("HOST:PORT")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("127.0.0.1:9900")
|
||||||
|
.help("Location of the drone; defaults to 127.0.0.1:9900"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("identity")
|
||||||
|
.short("i")
|
||||||
|
.long("identity")
|
||||||
|
.value_name("PATH")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("File containing a client identity (keypair)"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("threads")
|
||||||
|
.long("threads")
|
||||||
|
.value_name("<threads>")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("4")
|
||||||
|
.help("Number of threads submitting transactions"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("num-nodes")
|
||||||
|
.long("num-nodes")
|
||||||
|
.value_name("NUM")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("1")
|
||||||
|
.help("Wait for NUM nodes to converge"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("duration")
|
||||||
|
.long("duration")
|
||||||
|
.value_name("SECS")
|
||||||
|
.takes_value(true)
|
||||||
|
.default_value("60")
|
||||||
|
.help("Seconds to run benchmark, then exit; default is forever"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("trade-delay")
|
||||||
|
.long("trade-delay")
|
||||||
|
.value_name("<delay>")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("0")
|
||||||
|
.help("Delay between trade requests in milliseconds"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("fund-amount")
|
||||||
|
.long("fund-amount")
|
||||||
|
.value_name("<fund>")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("100000")
|
||||||
|
.help("Number of lamports to fund to each signer"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("batch-size")
|
||||||
|
.long("batch-size")
|
||||||
|
.value_name("<batch>")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("1000")
|
||||||
|
.help("Number of bulk trades to submit between trade delays"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("account-groups")
|
||||||
|
.long("account-groups")
|
||||||
|
.value_name("<groups>")
|
||||||
|
.takes_value(true)
|
||||||
|
.required(false)
|
||||||
|
.default_value("100")
|
||||||
|
.help("Number of account groups to cycle for each batch"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extract_args<'a>(matches: &ArgMatches<'a>) -> Config {
|
||||||
|
let mut args = Config::default();
|
||||||
|
|
||||||
|
args.network_addr = matches
|
||||||
|
.value_of("network")
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.expect("Failed to parse network");
|
||||||
|
args.drone_addr = matches
|
||||||
|
.value_of("drone")
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.expect("Failed to parse drone address");
|
||||||
|
|
||||||
|
if matches.is_present("identity") {
|
||||||
|
args.identity = read_keypair(matches.value_of("identity").unwrap())
|
||||||
|
.expect("can't read client identity");
|
||||||
|
} else {
|
||||||
|
args.identity = {
|
||||||
|
let seed = [42_u8; 32];
|
||||||
|
Keypair::from_seed_unchecked(Input::from(&seed)).unwrap()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
args.threads = value_t!(matches.value_of("threads"), usize).expect("Failed to parse threads");
|
||||||
|
args.num_nodes =
|
||||||
|
value_t!(matches.value_of("num-nodes"), usize).expect("Failed to parse num-nodes");
|
||||||
|
let duration = value_t!(matches.value_of("duration"), u64).expect("Failed to parse duration");
|
||||||
|
args.duration = Duration::from_secs(duration);
|
||||||
|
args.trade_delay =
|
||||||
|
value_t!(matches.value_of("trade-delay"), u64).expect("Failed to parse trade-delay");
|
||||||
|
args.fund_amount =
|
||||||
|
value_t!(matches.value_of("fund-amount"), u64).expect("Failed to parse fund-amount");
|
||||||
|
args.batch_size =
|
||||||
|
value_t!(matches.value_of("batch-size"), usize).expect("Failed to parse batch-size");
|
||||||
|
args.account_groups = value_t!(matches.value_of("account-groups"), usize)
|
||||||
|
.expect("Failed to parse account-groups");
|
||||||
|
|
||||||
|
args
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
pub mod bench;
|
||||||
|
mod cli;
|
||||||
|
pub mod order_book;
|
||||||
|
|
||||||
|
use crate::bench::{airdrop_lamports, do_bench_exchange, Config};
|
||||||
|
use log::*;
|
||||||
|
use solana::cluster_info::FULLNODE_PORT_RANGE;
|
||||||
|
use solana::gossip_service::discover_nodes;
|
||||||
|
use solana_client::thin_client::create_client;
|
||||||
|
use solana_client::thin_client::ThinClient;
|
||||||
|
use solana_sdk::signature::KeypairUtil;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let matches = cli::build_args().get_matches();
|
||||||
|
let cli_config = cli::extract_args(&matches);
|
||||||
|
|
||||||
|
let cli::Config {
|
||||||
|
network_addr,
|
||||||
|
drone_addr,
|
||||||
|
identity,
|
||||||
|
threads,
|
||||||
|
num_nodes,
|
||||||
|
duration,
|
||||||
|
trade_delay,
|
||||||
|
fund_amount,
|
||||||
|
batch_size,
|
||||||
|
account_groups,
|
||||||
|
..
|
||||||
|
} = cli_config;
|
||||||
|
|
||||||
|
info!("Connecting to the cluster");
|
||||||
|
let nodes = discover_nodes(&network_addr, num_nodes).unwrap_or_else(|_| {
|
||||||
|
panic!("Failed to discover nodes");
|
||||||
|
});
|
||||||
|
info!("{} nodes found", nodes.len());
|
||||||
|
if nodes.len() < num_nodes {
|
||||||
|
panic!("Error: Insufficient nodes discovered");
|
||||||
|
}
|
||||||
|
|
||||||
|
let client_ctors: Vec<_> = nodes
|
||||||
|
.iter()
|
||||||
|
.map(|node| {
|
||||||
|
let cluster_entrypoint = node.clone();
|
||||||
|
let cluster_addrs = cluster_entrypoint.client_facing_addr();
|
||||||
|
move || -> ThinClient { create_client(cluster_addrs, FULLNODE_PORT_RANGE) }
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
info!("Funding keypair: {}", identity.pubkey());
|
||||||
|
|
||||||
|
let client = client_ctors[0]();
|
||||||
|
let accounts_in_groups = batch_size * account_groups;
|
||||||
|
airdrop_lamports(
|
||||||
|
&client,
|
||||||
|
&drone_addr,
|
||||||
|
&identity,
|
||||||
|
fund_amount * (accounts_in_groups + 1) as u64 * 2,
|
||||||
|
);
|
||||||
|
|
||||||
|
let config = Config {
|
||||||
|
identity,
|
||||||
|
threads,
|
||||||
|
duration,
|
||||||
|
trade_delay,
|
||||||
|
fund_amount,
|
||||||
|
batch_size,
|
||||||
|
account_groups,
|
||||||
|
};
|
||||||
|
|
||||||
|
do_bench_exchange(client_ctors, config);
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
use itertools::EitherOrBoth::{Both, Left, Right};
|
||||||
|
use itertools::Itertools;
|
||||||
|
use log::*;
|
||||||
|
use solana_exchange_api::exchange_state::*;
|
||||||
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::collections::BinaryHeap;
|
||||||
|
use std::{error, fmt};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct ToOrder {
|
||||||
|
pub pubkey: Pubkey,
|
||||||
|
pub info: TradeOrderInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for ToOrder {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
other.info.price.cmp(&self.info.price)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialOrd for ToOrder {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub struct FromOrder {
|
||||||
|
pub pubkey: Pubkey,
|
||||||
|
pub info: TradeOrderInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for FromOrder {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.info.price.cmp(&other.info.price)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialOrd for FromOrder {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OrderBook {
|
||||||
|
// TODO scale to x token types
|
||||||
|
to_ab: BinaryHeap<ToOrder>,
|
||||||
|
from_ab: BinaryHeap<FromOrder>,
|
||||||
|
}
|
||||||
|
impl fmt::Display for OrderBook {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"+-Order Book--------------------------+-------------------------------------+"
|
||||||
|
)?;
|
||||||
|
for (i, it) in self
|
||||||
|
.to_ab
|
||||||
|
.iter()
|
||||||
|
.zip_longest(self.from_ab.iter())
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
match it {
|
||||||
|
Both(to, from) => writeln!(
|
||||||
|
f,
|
||||||
|
"| T AB {:8} for {:8}/{:8} | F AB {:8} for {:8}/{:8} |{}",
|
||||||
|
to.info.tokens,
|
||||||
|
SCALER,
|
||||||
|
to.info.price,
|
||||||
|
from.info.tokens,
|
||||||
|
SCALER,
|
||||||
|
from.info.price,
|
||||||
|
i
|
||||||
|
)?,
|
||||||
|
Left(to) => writeln!(
|
||||||
|
f,
|
||||||
|
"| T AB {:8} for {:8}/{:8} | |{}",
|
||||||
|
to.info.tokens, SCALER, to.info.price, i
|
||||||
|
)?,
|
||||||
|
Right(from) => writeln!(
|
||||||
|
f,
|
||||||
|
"| | F AB {:8} for {:8}/{:8} |{}",
|
||||||
|
from.info.tokens, SCALER, from.info.price, i
|
||||||
|
)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"+-------------------------------------+-------------------------------------+"
|
||||||
|
)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OrderBook {
|
||||||
|
// TODO
|
||||||
|
// pub fn cancel(&mut self, pubkey: Pubkey) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
// Ok(())
|
||||||
|
// }
|
||||||
|
pub fn push(
|
||||||
|
&mut self,
|
||||||
|
pubkey: Pubkey,
|
||||||
|
info: TradeOrderInfo,
|
||||||
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
|
check_trade(info.direction, info.tokens, info.price)?;
|
||||||
|
match info.direction {
|
||||||
|
Direction::To => {
|
||||||
|
self.to_ab.push(ToOrder { pubkey, info });
|
||||||
|
}
|
||||||
|
Direction::From => {
|
||||||
|
self.from_ab.push(FromOrder { pubkey, info });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn pop(&mut self) -> Option<(ToOrder, FromOrder)> {
|
||||||
|
if let Some(pair) = Self::pop_pair(&mut self.to_ab, &mut self.from_ab) {
|
||||||
|
return Some(pair);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
pub fn get_num_outstanding(&self) -> (usize, usize) {
|
||||||
|
(self.to_ab.len(), self.from_ab.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_pair(
|
||||||
|
to_ab: &mut BinaryHeap<ToOrder>,
|
||||||
|
from_ab: &mut BinaryHeap<FromOrder>,
|
||||||
|
) -> Option<(ToOrder, FromOrder)> {
|
||||||
|
let to = to_ab.peek()?;
|
||||||
|
let from = from_ab.peek()?;
|
||||||
|
if from.info.price < to.info.price {
|
||||||
|
debug!("Trade not viable");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let to = to_ab.pop()?;
|
||||||
|
let from = from_ab.pop()?;
|
||||||
|
Some((to, from))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue