mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-12 20:18:05 +00:00
fix: CI Clippy warnings
This commit is contained in:
@@ -6,12 +6,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Benchmark with Keep-Alive Enabled");
|
||||
println!("==================================\n");
|
||||
|
||||
let mut client = ClobClient::new("https://clob.polymarket.com");
|
||||
|
||||
let client = ClobClient::new("https://clob.polymarket.com");
|
||||
|
||||
// Start keep-alive
|
||||
println!("Starting keep-alive...");
|
||||
client.start_keepalive(Duration::from_secs(30)).await;
|
||||
|
||||
|
||||
// Give it a moment to establish
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
println!("Keep-alive started\n");
|
||||
@@ -21,24 +21,32 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Delay: 100ms between requests\n");
|
||||
|
||||
let mut times = Vec::new();
|
||||
|
||||
|
||||
for i in 1..=20 {
|
||||
let start = Instant::now();
|
||||
let response = client.http_client
|
||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
||||
let response = client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/simplified-markets?next_cursor=MA==",
|
||||
client.base_url
|
||||
))
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
|
||||
let _json: serde_json::Value = response.json().await?;
|
||||
let elapsed = start.elapsed();
|
||||
times.push(elapsed);
|
||||
|
||||
|
||||
if i <= 5 || i > 15 {
|
||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
||||
println!(
|
||||
" Request {:2}: {:.1} ms",
|
||||
i,
|
||||
elapsed.as_micros() as f64 / 1000.0
|
||||
);
|
||||
} else if i == 6 {
|
||||
println!(" ...");
|
||||
}
|
||||
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
@@ -46,14 +54,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
client.stop_keepalive().await;
|
||||
|
||||
// Calculate statistics
|
||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
||||
let values: Vec<f64> = times
|
||||
.iter()
|
||||
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||
.collect();
|
||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||
|
||||
let variance = values.iter()
|
||||
.map(|v| (v - mean).powi(2))
|
||||
.sum::<f64>() / values.len() as f64;
|
||||
|
||||
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||
let std_dev = variance.sqrt();
|
||||
|
||||
|
||||
let mut sorted = values.clone();
|
||||
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
let min = sorted[0];
|
||||
@@ -62,19 +71,25 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
println!("\n\n📊 RESULTS WITH KEEP-ALIVE");
|
||||
println!("===========================\n");
|
||||
|
||||
|
||||
println!("Mean: {:.1} ms ± {:.1} ms", mean, std_dev);
|
||||
println!("Median: {:.1} ms", median);
|
||||
println!("Range: {:.1} - {:.1} ms", min, max);
|
||||
|
||||
|
||||
println!("\nvs polymarket-rs-client: 404.5 ms ± 22.9 ms");
|
||||
println!("vs previous (no keep-alive): 382.6 ms ± 75.1 ms");
|
||||
|
||||
|
||||
let diff = mean - 404.5;
|
||||
if diff < 0.0 {
|
||||
println!("\n✅ {:.1}% FASTER than polymarket-rs-client", -diff / 404.5 * 100.0);
|
||||
println!(
|
||||
"\n✅ {:.1}% FASTER than polymarket-rs-client",
|
||||
-diff / 404.5 * 100.0
|
||||
);
|
||||
} else {
|
||||
println!("\n⚠️ {:.1}% slower than polymarket-rs-client", diff / 404.5 * 100.0);
|
||||
println!(
|
||||
"\n⚠️ {:.1}% slower than polymarket-rs-client",
|
||||
diff / 404.5 * 100.0
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
+42
-28
@@ -16,37 +16,42 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Delay: 100ms between requests\n");
|
||||
|
||||
let mut times = Vec::new();
|
||||
|
||||
|
||||
for i in 1..=20 {
|
||||
let start = Instant::now();
|
||||
let response = client
|
||||
.get("https://clob.polymarket.com/simplified-markets?next_cursor=MA==")
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
|
||||
let _json: serde_json::Value = response.json().await?;
|
||||
let elapsed = start.elapsed();
|
||||
times.push(elapsed);
|
||||
|
||||
|
||||
if i <= 5 || i > 15 {
|
||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
||||
println!(
|
||||
" Request {:2}: {:.1} ms",
|
||||
i,
|
||||
elapsed.as_micros() as f64 / 1000.0
|
||||
);
|
||||
} else if i == 6 {
|
||||
println!(" ...");
|
||||
}
|
||||
|
||||
|
||||
// 100ms delay like we used before
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
// Calculate statistics
|
||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
||||
let values: Vec<f64> = times
|
||||
.iter()
|
||||
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||
.collect();
|
||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||
|
||||
let variance = values.iter()
|
||||
.map(|v| (v - mean).powi(2))
|
||||
.sum::<f64>() / values.len() as f64;
|
||||
|
||||
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||
let std_dev = variance.sqrt();
|
||||
|
||||
|
||||
let mut sorted = values.clone();
|
||||
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap());
|
||||
let min = sorted[0];
|
||||
@@ -55,46 +60,55 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
println!("\n\n📊 FINAL RESULTS");
|
||||
println!("=================\n");
|
||||
|
||||
|
||||
println!("polyfill-rs Performance:");
|
||||
println!(" Mean: {:.1} ms ± {:.1} ms", mean, std_dev);
|
||||
println!(" Median: {:.1} ms", median);
|
||||
println!(" Range: {:.1} - {:.1} ms", min, max);
|
||||
|
||||
|
||||
println!("\n polymarket-rs-client (from their README):");
|
||||
println!(" Mean: 404.5 ms ± 22.9 ms");
|
||||
|
||||
|
||||
println!("\nOfficial Python Client (from their README):");
|
||||
println!(" Mean: 1366 ms ± 48 ms");
|
||||
|
||||
println!("\n\n📈 COMPARISON");
|
||||
println!("==============\n");
|
||||
|
||||
|
||||
let diff_vs_rust = mean - 404.5;
|
||||
let diff_pct_rust = (diff_vs_rust / 404.5) * 100.0;
|
||||
|
||||
|
||||
if diff_vs_rust < 0.0 {
|
||||
println!("vs polymarket-rs-client: {:.1}% FASTER ({:.1} ms faster)",
|
||||
-diff_pct_rust, -diff_vs_rust);
|
||||
println!(
|
||||
"vs polymarket-rs-client: {:.1}% FASTER ({:.1} ms faster)",
|
||||
-diff_pct_rust, -diff_vs_rust
|
||||
);
|
||||
} else if diff_pct_rust < 5.0 {
|
||||
println!("vs polymarket-rs-client: COMPETITIVE (within {:.1}%, +{:.1} ms)",
|
||||
diff_pct_rust, diff_vs_rust);
|
||||
println!(
|
||||
"vs polymarket-rs-client: COMPETITIVE (within {:.1}%, +{:.1} ms)",
|
||||
diff_pct_rust, diff_vs_rust
|
||||
);
|
||||
} else {
|
||||
println!("vs polymarket-rs-client: {:.1}% slower (+{:.1} ms)",
|
||||
diff_pct_rust, diff_vs_rust);
|
||||
println!(
|
||||
"vs polymarket-rs-client: {:.1}% slower (+{:.1} ms)",
|
||||
diff_pct_rust, diff_vs_rust
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
let speedup_vs_python = 1366.0 / mean;
|
||||
println!("vs Official Python: {:.1}x FASTER ({:.1} ms faster)",
|
||||
speedup_vs_python, 1366.0 - mean);
|
||||
|
||||
println!(
|
||||
"vs Official Python: {:.1}x FASTER ({:.1} ms faster)",
|
||||
speedup_vs_python,
|
||||
1366.0 - mean
|
||||
);
|
||||
|
||||
println!("\n\n🎯 VARIANCE ANALYSIS");
|
||||
println!("=====================\n");
|
||||
|
||||
|
||||
let variance_pct = (std_dev / mean) * 100.0;
|
||||
println!("Our variance: ±{:.1} ms ({:.1}%)", std_dev, variance_pct);
|
||||
println!("Their variance: ±22.9 ms (5.7%)");
|
||||
|
||||
|
||||
if std_dev < 30.0 {
|
||||
println!("\n✅ Excellent consistency!");
|
||||
} else if std_dev < 50.0 {
|
||||
|
||||
@@ -2,6 +2,7 @@ use reqwest::ClientBuilder;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
#[tokio::main]
|
||||
#[allow(unused_assignments)]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("HTTP/2 Configuration Tuning Benchmark");
|
||||
println!("======================================\n");
|
||||
@@ -26,9 +27,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
];
|
||||
|
||||
let max_frame_sizes = vec![
|
||||
None, // Default (16KB)
|
||||
Some(32 * 1024), // 32KB
|
||||
Some(64 * 1024), // 64KB
|
||||
None, // Default (16KB)
|
||||
Some(32 * 1024), // 32KB
|
||||
Some(64 * 1024), // 64KB
|
||||
];
|
||||
|
||||
let keep_alive_intervals = vec![
|
||||
@@ -72,10 +73,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Test 3: Connection window sizes (with best stream window from above)
|
||||
println!("\n\nTest 3: Connection Window Sizes");
|
||||
println!("================================");
|
||||
|
||||
|
||||
// Use 2MB stream window as a reasonable default for this test
|
||||
let default_stream_window = 2 * 1024 * 1024;
|
||||
|
||||
|
||||
for conn_window in &connection_windows {
|
||||
let client = ClientBuilder::new()
|
||||
.http2_adaptive_window(true)
|
||||
@@ -117,7 +118,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
None => "Frame: Default".to_string(),
|
||||
Some(s) => format!("Frame: {}KB", s / 1024),
|
||||
};
|
||||
|
||||
|
||||
let mean = test_config(client, &name).await?;
|
||||
|
||||
if mean < best_mean {
|
||||
@@ -159,7 +160,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("\nBest Configuration: {}", best_config.unwrap());
|
||||
println!("Best Mean Latency: {:.1} ms", best_mean);
|
||||
println!("\nBaseline (default): {:.1} ms", baseline_mean);
|
||||
|
||||
|
||||
let improvement = ((baseline_mean - best_mean) / baseline_mean) * 100.0;
|
||||
if improvement > 0.0 {
|
||||
println!("Improvement: {:.1}% faster", improvement);
|
||||
@@ -170,15 +171,18 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn std::error::Error>> {
|
||||
async fn test_config(
|
||||
client: reqwest::Client,
|
||||
name: &str,
|
||||
) -> Result<f64, Box<dyn std::error::Error>> {
|
||||
let iterations = 20;
|
||||
let mut times = Vec::new();
|
||||
|
||||
print!(" Testing {}... ", name);
|
||||
|
||||
|
||||
for _ in 0..iterations {
|
||||
let start = Instant::now();
|
||||
|
||||
|
||||
match client
|
||||
.get("https://clob.polymarket.com/simplified-markets?next_cursor=MA==")
|
||||
.send()
|
||||
@@ -189,11 +193,11 @@ async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn
|
||||
let _ = response.bytes().await;
|
||||
times.push(start.elapsed());
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// Skip failed requests
|
||||
continue;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
@@ -205,16 +209,17 @@ async fn test_config(client: reqwest::Client, name: &str) -> Result<f64, Box<dyn
|
||||
}
|
||||
|
||||
let mean = times.iter().sum::<Duration>().as_millis() as f64 / times.len() as f64;
|
||||
let variance = times.iter()
|
||||
let variance = times
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let diff = t.as_millis() as f64 - mean;
|
||||
diff * diff
|
||||
})
|
||||
.sum::<f64>() / times.len() as f64;
|
||||
.sum::<f64>()
|
||||
/ times.len() as f64;
|
||||
let std_dev = variance.sqrt();
|
||||
|
||||
println!("{:.1} ms ± {:.1} ms", mean, std_dev);
|
||||
|
||||
Ok(mean)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
use polyfill_rs::{ClobClient, OrderArgs, Side};
|
||||
use rust_decimal::Decimal;
|
||||
use std::str::FromStr;
|
||||
use polyfill_rs::ClobClient;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
async fn measure_multiple_runs<F, Fut, T>(name: &str, iterations: usize, mut f: F) -> Vec<Duration>
|
||||
where
|
||||
where
|
||||
F: FnMut() -> Fut,
|
||||
Fut: std::future::Future<Output = Result<T, Box<dyn std::error::Error>>>,
|
||||
{
|
||||
let mut times = Vec::new();
|
||||
let mut successes = 0;
|
||||
|
||||
|
||||
println!("🔄 Running {} iterations of {}...", iterations, name);
|
||||
|
||||
|
||||
for i in 0..iterations {
|
||||
let start = Instant::now();
|
||||
match f().await {
|
||||
@@ -23,44 +21,64 @@ where
|
||||
if i < 3 || i % 10 == 0 {
|
||||
println!(" ✅ Run {}: {}", i + 1, format_duration(duration));
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
let duration = start.elapsed();
|
||||
println!(" ❌ Run {}: {} (error: {})", i + 1, format_duration(duration), e);
|
||||
println!(
|
||||
" ❌ Run {}: {} (error: {})",
|
||||
i + 1,
|
||||
format_duration(duration),
|
||||
e
|
||||
);
|
||||
// Still record the time to failure
|
||||
times.push(duration);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
// Add small delay to avoid rate limiting
|
||||
if i < iterations - 1 {
|
||||
tokio::time::sleep(Duration::from_millis(100)).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if !times.is_empty() {
|
||||
times.sort();
|
||||
let mean = times.iter().sum::<Duration>() / times.len() as u32;
|
||||
let median = times[times.len() / 2];
|
||||
let min = times[0];
|
||||
let max = times[times.len() - 1];
|
||||
|
||||
|
||||
// Calculate standard deviation
|
||||
let variance: f64 = times.iter()
|
||||
let variance: f64 = times
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let diff = t.as_nanos() as f64 - mean.as_nanos() as f64;
|
||||
diff * diff
|
||||
})
|
||||
.sum::<f64>() / times.len() as f64;
|
||||
.sum::<f64>()
|
||||
/ times.len() as f64;
|
||||
let std_dev = Duration::from_nanos(variance.sqrt() as u64);
|
||||
|
||||
|
||||
println!("\n📊 {} Results:", name);
|
||||
println!(" Mean: {} ± {}", format_duration(mean), format_duration(std_dev));
|
||||
println!(" Range: {} to {}", format_duration(min), format_duration(max));
|
||||
println!(
|
||||
" Mean: {} ± {}",
|
||||
format_duration(mean),
|
||||
format_duration(std_dev)
|
||||
);
|
||||
println!(
|
||||
" Range: {} to {}",
|
||||
format_duration(min),
|
||||
format_duration(max)
|
||||
);
|
||||
println!(" Median: {}", format_duration(median));
|
||||
println!(" Success rate: {}/{} ({:.1}%)", successes, iterations, (successes as f64 / iterations as f64) * 100.0);
|
||||
println!(
|
||||
" Success rate: {}/{} ({:.1}%)",
|
||||
successes,
|
||||
iterations,
|
||||
(successes as f64 / iterations as f64) * 100.0
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
times
|
||||
}
|
||||
|
||||
@@ -98,7 +116,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.map_err(|_| "POLYMARKET_SECRET not found in .env file")?;
|
||||
let passphrase = std::env::var("POLYMARKET_PASSPHRASE")
|
||||
.map_err(|_| "POLYMARKET_PASSPHRASE not found in .env file")?;
|
||||
|
||||
|
||||
println!("✅ Loaded API credentials from environment");
|
||||
|
||||
// Create API credentials
|
||||
@@ -113,102 +131,156 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
client.set_api_creds(api_creds);
|
||||
|
||||
println!("✅ Client configured for custodial API trading");
|
||||
|
||||
|
||||
// Note: Pre-warming reduces variance but doesn't improve average speed
|
||||
// Using default client (Client::new()) is faster than optimized client
|
||||
|
||||
// Test 1: Market Data Fetching
|
||||
println!("\n📊 Test 1: Market Data Fetching & Parsing");
|
||||
println!("=========================================");
|
||||
|
||||
|
||||
let market_times = measure_multiple_runs("Market Data Fetch", 10, || async {
|
||||
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
||||
let response = client.http_client
|
||||
.get(format!("{}/sampling-markets?next_cursor=MA==", client.base_url))
|
||||
let response = client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/sampling-markets?next_cursor=MA==",
|
||||
client.base_url
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
let json: serde_json::Value = response.json().await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
let json: serde_json::Value = response.json().await.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
// Just verify we got data
|
||||
if json["data"].as_array().is_some() {
|
||||
Ok(json)
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Invalid response")) as Box<dyn std::error::Error>)
|
||||
Err(Box::new(std::io::Error::other(
|
||||
"Invalid response",
|
||||
)) as Box<dyn std::error::Error>)
|
||||
}
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
|
||||
// Test 2: Authenticated API endpoint (simplified markets)
|
||||
println!("\n📝 Test 2: Authenticated Simplified Markets");
|
||||
println!("============================================");
|
||||
|
||||
|
||||
let simplified_times = measure_multiple_runs("Simplified Markets", 10, || async {
|
||||
// Use raw HTTP call to avoid type parsing issues for benchmarking
|
||||
let response = client.http_client
|
||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
||||
let response = client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/simplified-markets?next_cursor=MA==",
|
||||
client.base_url
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
let json: serde_json::Value = response.json().await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
let json: serde_json::Value = response.json().await.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
// Just verify we got data
|
||||
if json["data"].as_array().is_some() {
|
||||
Ok(json)
|
||||
} else {
|
||||
Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Invalid response")) as Box<dyn std::error::Error>)
|
||||
Err(Box::new(std::io::Error::other(
|
||||
"Invalid response",
|
||||
)) as Box<dyn std::error::Error>)
|
||||
}
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
|
||||
// Test 3: Multiple Market Data Requests (batch performance)
|
||||
println!("\n🔄 Test 3: Batch Market Operations");
|
||||
println!("==================================");
|
||||
|
||||
|
||||
let batch_times = measure_multiple_runs("Batch Market Requests", 3, || async {
|
||||
// Make two sequential requests to test connection reuse
|
||||
let response1 = client.http_client
|
||||
.get(format!("{}/sampling-markets?next_cursor=MA==", client.base_url))
|
||||
let response1 = client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/sampling-markets?next_cursor=MA==",
|
||||
client.base_url
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
let json1: serde_json::Value = response1.json().await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
let response2 = client.http_client
|
||||
.get(format!("{}/simplified-markets?next_cursor=MA==", client.base_url))
|
||||
.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
let json1: serde_json::Value = response1.json().await.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
let response2 = client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/simplified-markets?next_cursor=MA==",
|
||||
client.base_url
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
let json2: serde_json::Value = response2.json().await
|
||||
.map_err(|e| Box::new(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())) as Box<dyn std::error::Error>)?;
|
||||
|
||||
.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
let json2: serde_json::Value = response2.json().await.map_err(|e| {
|
||||
Box::new(std::io::Error::other(
|
||||
e.to_string(),
|
||||
)) as Box<dyn std::error::Error>
|
||||
})?;
|
||||
|
||||
// Count markets
|
||||
let count1 = json1["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
||||
let count2 = json2["data"].as_array().map(|a| a.len()).unwrap_or(0);
|
||||
|
||||
|
||||
Ok(count1 + count2)
|
||||
}).await;
|
||||
})
|
||||
.await;
|
||||
|
||||
// Summary
|
||||
println!("\n📈 BENCHMARK SUMMARY");
|
||||
println!("===================");
|
||||
|
||||
|
||||
|
||||
if !market_times.is_empty() {
|
||||
let market_mean = market_times.iter().sum::<Duration>() / market_times.len() as u32;
|
||||
println!("📊 Market Data Fetch: {}", format_duration(market_mean));
|
||||
}
|
||||
|
||||
|
||||
if !simplified_times.is_empty() {
|
||||
let simplified_mean = simplified_times.iter().sum::<Duration>() / simplified_times.len() as u32;
|
||||
println!("📝 Simplified Markets: {}", format_duration(simplified_mean));
|
||||
let simplified_mean =
|
||||
simplified_times.iter().sum::<Duration>() / simplified_times.len() as u32;
|
||||
println!(
|
||||
"📝 Simplified Markets: {}",
|
||||
format_duration(simplified_mean)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if !batch_times.is_empty() {
|
||||
let batch_mean = batch_times.iter().sum::<Duration>() / batch_times.len() as u32;
|
||||
println!("🔄 Batch Operations: {}", format_duration(batch_mean));
|
||||
@@ -224,6 +296,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("- Polymarket uses custodial, off-chain trading");
|
||||
println!("- No Ethereum private key or on-chain signing required");
|
||||
println!("- Only API credentials (key, secret, passphrase) needed");
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//! Side-by-side benchmark comparing polyfill-rs vs polymarket-rs-client
|
||||
//!
|
||||
//!
|
||||
//! To run this benchmark, uncomment the polymarket-rs-client dependency in Cargo.toml:
|
||||
//! ```toml
|
||||
//! [dev-dependencies]
|
||||
@@ -25,9 +25,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("══════════════════════════════════════");
|
||||
println!("Test 1: polymarket-rs-client");
|
||||
println!("══════════════════════════════════════");
|
||||
|
||||
|
||||
let their_client = polymarket_rs_client::ClobClient::new("https://clob.polymarket.com");
|
||||
|
||||
|
||||
let mut their_times = Vec::new();
|
||||
for i in 1..=20 {
|
||||
let start = Instant::now();
|
||||
@@ -35,18 +35,22 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(_markets) => {
|
||||
let elapsed = start.elapsed();
|
||||
their_times.push(elapsed);
|
||||
|
||||
|
||||
if i <= 3 || i > 17 {
|
||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
||||
println!(
|
||||
" Request {:2}: {:.1} ms",
|
||||
i,
|
||||
elapsed.as_micros() as f64 / 1000.0
|
||||
);
|
||||
} else if i == 4 {
|
||||
println!(" ...");
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!(" Request {:2}: ERROR - {}", i, e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
@@ -57,41 +61,49 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("\n══════════════════════════════════════");
|
||||
println!("Test 2: polyfill-rs (with keep-alive)");
|
||||
println!("══════════════════════════════════════");
|
||||
|
||||
|
||||
let our_client = polyfill_rs::ClobClient::new("https://clob.polymarket.com");
|
||||
our_client.start_keepalive(std::time::Duration::from_secs(30)).await;
|
||||
our_client
|
||||
.start_keepalive(std::time::Duration::from_secs(30))
|
||||
.await;
|
||||
tokio::time::sleep(std::time::Duration::from_millis(500)).await; // Let keep-alive establish
|
||||
|
||||
|
||||
let mut our_times = Vec::new();
|
||||
for i in 1..=20 {
|
||||
let start = Instant::now();
|
||||
match our_client.http_client
|
||||
.get(format!("{}/simplified-markets?next_cursor=MA==", our_client.base_url))
|
||||
match our_client
|
||||
.http_client
|
||||
.get(format!(
|
||||
"{}/simplified-markets?next_cursor=MA==",
|
||||
our_client.base_url
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(response) => {
|
||||
match response.json::<serde_json::Value>().await {
|
||||
Ok(_json) => {
|
||||
let elapsed = start.elapsed();
|
||||
our_times.push(elapsed);
|
||||
|
||||
if i <= 3 || i > 17 {
|
||||
println!(" Request {:2}: {:.1} ms", i, elapsed.as_micros() as f64 / 1000.0);
|
||||
} else if i == 4 {
|
||||
println!(" ...");
|
||||
}
|
||||
Ok(response) => match response.json::<serde_json::Value>().await {
|
||||
Ok(_json) => {
|
||||
let elapsed = start.elapsed();
|
||||
our_times.push(elapsed);
|
||||
|
||||
if i <= 3 || i > 17 {
|
||||
println!(
|
||||
" Request {:2}: {:.1} ms",
|
||||
i,
|
||||
elapsed.as_micros() as f64 / 1000.0
|
||||
);
|
||||
} else if i == 4 {
|
||||
println!(" ...");
|
||||
}
|
||||
Err(e) => {
|
||||
println!(" Request {:2}: PARSE ERROR - {}", i, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
println!(" Request {:2}: PARSE ERROR - {}", i, e);
|
||||
},
|
||||
},
|
||||
Err(e) => {
|
||||
println!(" Request {:2}: NETWORK ERROR - {}", i, e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
}
|
||||
|
||||
@@ -102,8 +114,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
if times.is_empty() {
|
||||
return (0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
let values: Vec<f64> = times.iter().map(|d| d.as_micros() as f64 / 1000.0).collect();
|
||||
|
||||
let values: Vec<f64> = times
|
||||
.iter()
|
||||
.map(|d| d.as_micros() as f64 / 1000.0)
|
||||
.collect();
|
||||
let mean = values.iter().sum::<f64>() / values.len() as f64;
|
||||
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
|
||||
let std_dev = variance.sqrt();
|
||||
@@ -143,29 +158,43 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
println!("\n");
|
||||
println!("═══════════════════════════════════════════════════════");
|
||||
|
||||
|
||||
if our_times.is_empty() || their_times.is_empty() {
|
||||
println!("ERROR: Not enough successful requests to compare");
|
||||
} else {
|
||||
let diff = our_mean - their_mean;
|
||||
let pct = (diff.abs() / their_mean) * 100.0;
|
||||
|
||||
|
||||
if diff < 0.0 {
|
||||
println!("✅ polyfill-rs is {:.1}% FASTER ({:.1} ms faster)", pct, -diff);
|
||||
println!(
|
||||
"✅ polyfill-rs is {:.1}% FASTER ({:.1} ms faster)",
|
||||
pct, -diff
|
||||
);
|
||||
} else {
|
||||
println!("❌ polymarket-rs-client is {:.1}% faster ({:.1} ms faster)", pct, diff);
|
||||
println!(
|
||||
"❌ polymarket-rs-client is {:.1}% faster ({:.1} ms faster)",
|
||||
pct, diff
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
println!("═══════════════════════════════════════════════════════");
|
||||
|
||||
// Detailed variance comparison
|
||||
println!("\n\nVariance Analysis:");
|
||||
println!("────────────────────────────────────────────────────");
|
||||
println!(" polymarket-rs-client: ±{:.1} ms ({:.1}% variance)", their_std, (their_std/their_mean)*100.0);
|
||||
println!(" polyfill-rs: ±{:.1} ms ({:.1}% variance)", our_std, (our_std/our_mean)*100.0);
|
||||
println!(
|
||||
" polymarket-rs-client: ±{:.1} ms ({:.1}% variance)",
|
||||
their_std,
|
||||
(their_std / their_mean) * 100.0
|
||||
);
|
||||
println!(
|
||||
" polyfill-rs: ±{:.1} ms ({:.1}% variance)",
|
||||
our_std,
|
||||
(our_std / our_mean) * 100.0
|
||||
);
|
||||
println!();
|
||||
|
||||
|
||||
if our_std < their_std {
|
||||
let improvement = ((their_std - our_std) / their_std) * 100.0;
|
||||
println!(" ✅ polyfill-rs is {:.1}% more consistent", improvement);
|
||||
@@ -177,29 +206,36 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Claims validation
|
||||
println!("\n\nClaims Validation:");
|
||||
println!("────────────────────────────────────────────────────");
|
||||
|
||||
|
||||
let their_claimed_mean = 404.5;
|
||||
let their_claimed_std = 22.9;
|
||||
let our_claimed_mean = 368.6;
|
||||
let our_claimed_std = 67.1;
|
||||
|
||||
|
||||
let their_mean_diff = ((their_mean - their_claimed_mean).abs() / their_claimed_mean) * 100.0;
|
||||
let their_std_diff = ((their_std - their_claimed_std).abs() / their_claimed_std) * 100.0;
|
||||
let our_mean_diff = ((our_mean - our_claimed_mean).abs() / our_claimed_mean) * 100.0;
|
||||
let our_std_diff = ((our_std - our_claimed_std).abs() / our_claimed_std) * 100.0;
|
||||
|
||||
|
||||
println!("polymarket-rs-client claimed vs actual:");
|
||||
println!(" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||
their_claimed_mean, their_mean, their_mean_diff);
|
||||
println!(" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||
their_claimed_std, their_std, their_std_diff);
|
||||
|
||||
println!(
|
||||
" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||
their_claimed_mean, their_mean, their_mean_diff
|
||||
);
|
||||
println!(
|
||||
" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||
their_claimed_std, their_std, their_std_diff
|
||||
);
|
||||
|
||||
println!("\npolyfill-rs claimed vs actual:");
|
||||
println!(" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||
our_claimed_mean, our_mean, our_mean_diff);
|
||||
println!(" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||
our_claimed_std, our_std, our_std_diff);
|
||||
println!(
|
||||
" Mean: {:.1} ms vs {:.1} ms ({:.1}% difference)",
|
||||
our_claimed_mean, our_mean, our_mean_diff
|
||||
);
|
||||
println!(
|
||||
" Variance: ±{:.1} ms vs ±{:.1} ms ({:.1}% difference)",
|
||||
our_claimed_std, our_std, our_std_diff
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user