add complete binary and benchmarking
This commit is contained in:
324
benches/horus_stack.rs
Normal file
324
benches/horus_stack.rs
Normal file
@@ -0,0 +1,324 @@
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
|
||||
use hero_supervisor_openrpc_client::SupervisorClientBuilder;
|
||||
use hero_job::Job;
|
||||
use tokio::runtime::Runtime;
|
||||
use std::time::Duration;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
use chrono::Utc;
|
||||
|
||||
/// Benchmark configuration
|
||||
const SUPERVISOR_URL: &str = "http://127.0.0.1:3030";
|
||||
const OSIRIS_URL: &str = "http://127.0.0.1:8081";
|
||||
const ADMIN_SECRET: &str = "SECRET";
|
||||
|
||||
/// Helper to create a tokio runtime for benchmarks
|
||||
fn create_runtime() -> Runtime {
|
||||
Runtime::new().unwrap()
|
||||
}
|
||||
|
||||
/// Helper to create a test job
|
||||
fn create_test_job(runner: &str, command: &str, args: Vec<String>) -> Job {
|
||||
Job {
|
||||
id: Uuid::new_v4().to_string(),
|
||||
caller_id: "benchmark".to_string(),
|
||||
context_id: "test".to_string(),
|
||||
payload: serde_json::json!({
|
||||
"command": command,
|
||||
"args": args
|
||||
}).to_string(),
|
||||
runner: runner.to_string(),
|
||||
timeout: 30,
|
||||
env_vars: HashMap::new(),
|
||||
created_at: Utc::now(),
|
||||
updated_at: Utc::now(),
|
||||
signatures: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Benchmark: Supervisor discovery (OpenRPC metadata)
|
||||
fn bench_supervisor_discovery(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
c.bench_function("supervisor_discovery", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.discover().await.expect("Discovery failed"))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Supervisor info retrieval
|
||||
fn bench_supervisor_info(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
c.bench_function("supervisor_get_info", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.get_supervisor_info().await.expect("Get info failed"))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: List runners
|
||||
fn bench_list_runners(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
c.bench_function("supervisor_list_runners", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.runner_list().await.expect("List runners failed"))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Job creation (without execution)
|
||||
fn bench_job_create(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
// Ensure runner exists
|
||||
rt.block_on(async {
|
||||
let _ = client.runner_create("hero").await;
|
||||
});
|
||||
|
||||
c.bench_function("supervisor_job_create", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
let job = create_test_job("hero", "echo", vec!["hello".to_string()]);
|
||||
black_box(client.job_create(job).await.expect("Job create failed"))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Job listing
|
||||
fn bench_job_list(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
c.bench_function("supervisor_job_list", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.job_list().await.expect("Job list failed"))
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Osiris health check
|
||||
fn bench_osiris_health(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
c.bench_function("osiris_health_check", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
let url = format!("{}/health", OSIRIS_URL);
|
||||
black_box(
|
||||
client
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.expect("Health check failed")
|
||||
.json::<serde_json::Value>()
|
||||
.await
|
||||
.expect("JSON parse failed")
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Full job lifecycle (create, start, wait for result)
|
||||
fn bench_job_lifecycle(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.timeout(Duration::from_secs(60))
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
// First ensure we have a runner registered
|
||||
rt.block_on(async {
|
||||
let _ = client.runner_create("hero").await;
|
||||
});
|
||||
|
||||
c.bench_function("job_full_lifecycle", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
let job = create_test_job("hero", "echo", vec!["benchmark_test".to_string()]);
|
||||
|
||||
// Start job and wait for result
|
||||
black_box(
|
||||
client
|
||||
.job_run(job, Some(30))
|
||||
.await
|
||||
.expect("Job run failed")
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: Concurrent job submissions
|
||||
fn bench_concurrent_jobs(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.timeout(Duration::from_secs(60))
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
// Ensure runner is registered
|
||||
rt.block_on(async {
|
||||
let _ = client.runner_create("hero").await;
|
||||
});
|
||||
|
||||
let mut group = c.benchmark_group("concurrent_jobs");
|
||||
|
||||
for num_jobs in [1, 5, 10, 20].iter() {
|
||||
group.bench_with_input(
|
||||
BenchmarkId::from_parameter(num_jobs),
|
||||
num_jobs,
|
||||
|b, &num_jobs| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
let mut handles = vec![];
|
||||
|
||||
for i in 0..num_jobs {
|
||||
let client = client.clone();
|
||||
let handle = tokio::spawn(async move {
|
||||
let job = create_test_job("hero", "echo", vec![format!("job_{}", i)]);
|
||||
client.job_create(job).await
|
||||
});
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// Wait for all jobs to be submitted
|
||||
for handle in handles {
|
||||
black_box(handle.await.expect("Task failed").expect("Job start failed"));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
/// Benchmark: Runner status checks
|
||||
fn bench_runner_status(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
// Ensure we have runners
|
||||
rt.block_on(async {
|
||||
let _ = client.runner_create("hero").await;
|
||||
let _ = client.runner_create("osiris").await;
|
||||
});
|
||||
|
||||
c.bench_function("get_all_runner_status", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(
|
||||
client
|
||||
.get_all_runner_status()
|
||||
.await
|
||||
.expect("Get status failed")
|
||||
)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// Benchmark: API response time under load
|
||||
fn bench_api_latency(c: &mut Criterion) {
|
||||
let rt = create_runtime();
|
||||
|
||||
let client = rt.block_on(async {
|
||||
SupervisorClientBuilder::new()
|
||||
.url(SUPERVISOR_URL)
|
||||
.secret(ADMIN_SECRET)
|
||||
.build()
|
||||
.expect("Failed to create supervisor client")
|
||||
});
|
||||
|
||||
let mut group = c.benchmark_group("api_latency");
|
||||
group.measurement_time(Duration::from_secs(10));
|
||||
|
||||
group.bench_function("supervisor_info", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.get_supervisor_info().await.expect("Failed"))
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("runner_list", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.runner_list().await.expect("Failed"))
|
||||
});
|
||||
});
|
||||
|
||||
group.bench_function("job_list", |b| {
|
||||
b.to_async(&rt).iter(|| async {
|
||||
black_box(client.job_list().await.expect("Failed"))
|
||||
});
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_supervisor_discovery,
|
||||
bench_supervisor_info,
|
||||
bench_list_runners,
|
||||
bench_job_create,
|
||||
bench_job_list,
|
||||
bench_osiris_health,
|
||||
bench_job_lifecycle,
|
||||
bench_concurrent_jobs,
|
||||
bench_runner_status,
|
||||
bench_api_latency,
|
||||
);
|
||||
|
||||
criterion_main!(benches);
|
||||
Reference in New Issue
Block a user