mod common;
use rust_dix::*;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use tokio::time::Instant;
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn bench_async_scoped_100_concurrent_empty_factory() {
static CALLS: AtomicU64 = AtomicU64::new(0);
let provider = ServiceCollection::new()
.async_scoped(|_| {
Box::pin(async {
CALLS.fetch_add(1, Ordering::SeqCst);
Arc::new(common::MyService { value: 42 })
})
})
.build_async()
.await
.unwrap();
let scope = provider.scope();
let start = Instant::now();
let mut handles = Vec::with_capacity(100);
for _ in 0..100 {
let sp = scope.scope_provider().clone();
handles.push(tokio::spawn(async move {
sp.get_async::<common::MyService>().await.unwrap()
}));
}
let results = futures::future::join_all(handles).await;
let elapsed = start.elapsed();
assert_eq!(
CALLS.load(Ordering::SeqCst),
1,
"100 并发:async factory 应只执行一次"
);
let first = results[0].as_ref().unwrap();
for (i, r) in results.iter().enumerate() {
assert!(
Arc::ptr_eq(first, r.as_ref().unwrap()),
"任务 {} 应拿到同一实例",
i
);
}
println!(
"bench_async_scoped_100_concurrent_empty_factory: {:?} (100 并发, FuturesMutex 纯开销)",
elapsed
);
assert!(
elapsed < std::time::Duration::from_millis(500),
"100 并发空工厂解析耗时应 < 500ms, 实际 {:?}",
elapsed
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn bench_async_scoped_100_concurrent_with_delay() {
static CALLS: AtomicU64 = AtomicU64::new(0);
let provider = ServiceCollection::new()
.async_scoped(|_| {
Box::pin(async {
CALLS.fetch_add(1, Ordering::SeqCst);
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
Arc::new(common::MyService { value: 99 })
})
})
.build_async()
.await
.unwrap();
let scope = provider.scope();
let start = Instant::now();
let mut handles = Vec::with_capacity(100);
for _ in 0..100 {
let sp = scope.scope_provider().clone();
handles.push(tokio::spawn(async move {
sp.get_async::<common::MyService>().await.unwrap()
}));
}
let results = futures::future::join_all(handles).await;
let elapsed = start.elapsed();
assert_eq!(
CALLS.load(Ordering::SeqCst),
1,
"带延迟工厂:async factory 应只执行一次"
);
let first = results[0].as_ref().unwrap();
for r in &results {
assert!(Arc::ptr_eq(first, r.as_ref().unwrap()));
}
println!(
"bench_async_scoped_100_concurrent_with_delay: {:?} (100 并发, 10ms 工厂延迟, 串行需 1000ms)",
elapsed
);
assert!(
elapsed < std::time::Duration::from_millis(200),
"100 并发带延迟解析应 < 200ms (串行需 1000ms), 实际 {:?}",
elapsed
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
async fn bench_sync_scoped_100_concurrent_baseline() {
static CALLS: AtomicU64 = AtomicU64::new(0);
let provider = ServiceCollection::new()
.scoped(|_| {
CALLS.fetch_add(1, Ordering::SeqCst);
Arc::new(common::MyService { value: 7 })
})
.build()
.unwrap();
let scope = provider.scope();
let start = Instant::now();
let mut handles = Vec::with_capacity(100);
for _ in 0..100 {
let sp = scope.scope_provider().clone();
handles.push(tokio::task::spawn_blocking(move || {
sp.get::<common::MyService>().unwrap()
}));
}
let results = futures::future::join_all(handles).await;
let elapsed = start.elapsed();
assert_eq!(
CALLS.load(Ordering::SeqCst),
1,
"sync 基线:factory 应只执行一次"
);
let first = results[0].as_ref().unwrap();
for r in &results {
assert!(Arc::ptr_eq(first, r.as_ref().unwrap()));
}
println!(
"bench_sync_scoped_100_concurrent_baseline: {:?} (100 并发, OnceLock 基线)",
elapsed
);
assert!(
elapsed < std::time::Duration::from_millis(500),
"100 并发 sync 基线解析应 < 500ms, 实际 {:?}",
elapsed
);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 8)]
async fn stress_async_scoped_1000_concurrent() {
static CALLS: AtomicU64 = AtomicU64::new(0);
let provider = ServiceCollection::new()
.async_scoped(|_| {
Box::pin(async {
CALLS.fetch_add(1, Ordering::SeqCst);
Arc::new(common::MyService { value: 1000 })
})
})
.build_async()
.await
.unwrap();
let scope = provider.scope();
let start = Instant::now();
let mut handles = Vec::with_capacity(1000);
for _ in 0..1000 {
let sp = scope.scope_provider().clone();
handles.push(tokio::spawn(async move {
sp.get_async::<common::MyService>().await.unwrap()
}));
}
let results = futures::future::join_all(handles).await;
let elapsed = start.elapsed();
assert_eq!(
CALLS.load(Ordering::SeqCst),
1,
"1000 并发:async factory 应只执行一次"
);
let first = results[0].as_ref().unwrap();
for r in &results {
assert!(Arc::ptr_eq(first, r.as_ref().unwrap()));
}
println!(
"stress_async_scoped_1000_concurrent: {:?} (1000 并发, 8 worker threads)",
elapsed
);
assert!(
elapsed < std::time::Duration::from_secs(2),
"1000 并发压力测试应 < 2s, 实际 {:?}",
elapsed
);
}