Address soundness hole in cycle prevention

This commit is contained in:
TechnoPorg committed 2026-01-29 06:56:17 +01:00
1 parent 4ad88bcd68
commit f82205baf4
80 files changed
+730 -717

No files matched your search

+16 -14
View File
@@ -1,7 +1,7 @@
//! Configuration broadcast pattern benchmark - one config shared across many workers
use criterion::{BenchmarkId, Criterion};
use dagx::{task_fn, DagRunner};
use dagx::{task_fn, DagRunner, TaskHandle};
use futures::FutureExt;
use std::collections::HashMap;
use std::hint::black_box;
@@ -20,18 +20,20 @@ pub fn bench_config_broadcast(c: &mut Criterion) {
let dag = DagRunner::new();
// Configuration source - framework wraps HashMap in Arc automatically
let config = dag.add_task(task_fn(|_: ()| async {
HashMap::from([
("max_connections".to_string(), "100".to_string()),
("timeout_ms".to_string(), "5000".to_string()),
("batch_size".to_string(), "50".to_string()),
("retry_count".to_string(), "3".to_string()),
("worker_threads".to_string(), "4".to_string()),
("buffer_size".to_string(), "8192".to_string()),
("compression".to_string(), "true".to_string()),
("log_level".to_string(), "info".to_string()),
])
}));
let config: TaskHandle<_> = dag
.add_task(task_fn(|_: ()| async {
HashMap::from([
("max_connections".to_string(), "100".to_string()),
("timeout_ms".to_string(), "5000".to_string()),
("batch_size".to_string(), "50".to_string()),
("retry_count".to_string(), "3".to_string()),
("worker_threads".to_string(), "4".to_string()),
("buffer_size".to_string(), "8192".to_string()),
("compression".to_string(), "true".to_string()),
("log_level".to_string(), "info".to_string()),
])
}))
.into();
// Workers receive and process based on shared config
for worker_id in 0..workers {
@@ -49,7 +51,7 @@ pub fn bench_config_broadcast(c: &mut Criterion) {
// Simulate some computation
black_box(worker_id * batch_size + timeout / 100)
}))
.depends_on(&config);
.depends_on(config);
}
dag.run(|fut| tokio::spawn(fut).map(Result::unwrap))
+6 -6
View File
@@ -1,7 +1,7 @@
//! ETL (Extract, Transform, Load) pipeline benchmark
use criterion::{BenchmarkId, Criterion};
use dagx::{task_fn, DagRunner};
use dagx::{task_fn, DagRunner, TaskHandle};
use futures::FutureExt;
pub fn bench_etl_pipeline(c: &mut Criterion) {
@@ -21,7 +21,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) {
let dag = DagRunner::new();
// Extract: Load JSON-like data (framework wraps in Arc automatically)
let extract = dag.add_task(task_fn(move |_: ()| async move {
let extract: TaskHandle<_> = dag.add_task(task_fn(move |_: ()| async move {
(0..count)
.map(|i| {
format!(
@@ -32,7 +32,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) {
)
})
.collect::<Vec<_>>()
}));
})).into();
// Transform: Three parallel transformations
@@ -47,7 +47,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) {
})
.count()
}))
.depends_on(&extract);
.depends_on(extract);
// T2: Extract scores
let scores = dag
@@ -60,7 +60,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) {
})
.collect::<Vec<_>>()
}))
.depends_on(&extract);
.depends_on(extract);
// T3: Extract names
let names = dag
@@ -74,7 +74,7 @@ pub fn bench_etl_pipeline(c: &mut Criterion) {
})
.collect::<Vec<_>>()
}))
.depends_on(&extract);
.depends_on(extract);
// Load: Aggregate all transformations
dag.add_task(task_fn(
+8 -6
View File
@@ -1,7 +1,7 @@
//! Memory efficiency benchmark with large data structures
use criterion::{BenchmarkId, Criterion};
use dagx::{task_fn, DagRunner};
use dagx::{task_fn, DagRunner, TaskHandle};
use futures::FutureExt;
use std::hint::black_box;
@@ -19,10 +19,12 @@ pub fn bench_memory_efficiency(c: &mut Criterion) {
rt.block_on(async {
let dag = DagRunner::new();
let source = dag.add_task(task_fn(move |_: ()| async move {
// Create MB of data - framework wraps in Arc automatically
vec![0u8; mb * 1024 * 1024]
}));
let source: TaskHandle<_> = dag
.add_task(task_fn(move |_: ()| async move {
// Create MB of data - framework wraps in Arc automatically
vec![0u8; mb * 1024 * 1024]
}))
.into();
// 20 consumers share the data via automatic Arc wrapping
for i in 0..20 {
@@ -36,7 +38,7 @@ pub fn bench_memory_efficiency(c: &mut Criterion) {
.sum();
black_box(sample_sum)
}))
.depends_on(&source);
.depends_on(source);
}
dag.run(|fut| tokio::spawn(fut).map(Result::unwrap))
+11 -9
View File
@@ -1,7 +1,7 @@
//! Mixed realistic patterns - fan-out, fan-in, and processing
use criterion::Criterion;
use dagx::{task_fn, DagRunner};
use dagx::{task_fn, DagRunner, TaskHandle};
use futures::FutureExt;
pub fn bench_mixed_patterns(c: &mut Criterion) {
@@ -13,28 +13,30 @@ pub fn bench_mixed_patterns(c: &mut Criterion) {
let dag = DagRunner::new();
// Stage 1: Load data (framework wraps in Arc automatically)
let data = dag.add_task(task_fn(|_: ()| async {
(0..1000)
.map(|i| format!("Record-{:04}", i))
.collect::<Vec<_>>()
}));
let data: TaskHandle<_> = dag
.add_task(task_fn(|_: ()| async {
(0..1000)
.map(|i| format!("Record-{:04}", i))
.collect::<Vec<_>>()
}))
.into();
// Stage 2: Fan-out for parallel analysis
let analysis1 = dag
.add_task(task_fn(|d: Vec<String>| async move {
d.iter().filter(|s| s.contains("00")).count()
}))
.depends_on(&data);
.depends_on(data);
let analysis2 = dag
.add_task(task_fn(|d: Vec<String>| async move {
d.iter().map(|s| s.len()).sum::<usize>()
}))
.depends_on(&data);
.depends_on(data);
let analysis3 = dag
.add_task(task_fn(|d: Vec<String>| async move { d.len() }))
.depends_on(&data);
.depends_on(data);
// Stage 3: Fan-in to aggregate
let summary = dag