wave9 complete: 458/207 — airflow/argo/pytorch-0003/tf/jax/pyg/grpc/thrift + graphhopper/valhalla

This commit is contained in:
russell@unturf.com 2026-03-27 16:59:04 -04:00
parent 81bc62b9cb
commit ab10b2f555
22 changed files with 2889 additions and 16 deletions

View file

@ -0,0 +1,245 @@
package unit;
import java.util.*;
/**
* argo-0001 O(N) linear GetTask() scan inside O(N) DAG execution loop
*
* Simulates the defective GetTask() from:
* workflow/controller/dag.go:83-89
*
* Defect: dagContext stores tasks as []DAGTask (slice). GetTask(name) does
* linear scan. Called O(N) times per executeDAG() cycle O(N²) total.
*
* Fix: Build a map[string]*DAGTask at dagContext construction time O(1) lookup.
*
* The unit test simulates:
* 1. A DAGContext with N tasks (stored as list in defective, map in fixed)
* 2. An executeDAG loop that calls GetTask() once per targetTask
* 3. Counts total comparisons to confirm O(N²) vs O(N)
*/
public class ArgoGetTaskAlgorithm {
static int opCount = 0;
static void check(String desc, boolean cond) {
System.out.println((cond ? "PASS" : "FAIL") + ": " + desc);
if (!cond) throw new AssertionError("FAIL: " + desc);
}
// -----------------------------------------------------------------------
// Simulated DAGTask
// -----------------------------------------------------------------------
static class DAGTask {
final String name;
final List<String> dependencies;
DAGTask(String name, List<String> deps) {
this.name = name;
this.dependencies = deps;
}
}
// -----------------------------------------------------------------------
// DEFECTIVE: tasks stored as List<DAGTask>, GetTask does linear scan
// -----------------------------------------------------------------------
static class DefectiveDagContext {
final List<DAGTask> tasks;
DefectiveDagContext(List<DAGTask> tasks) {
this.tasks = new ArrayList<>(tasks);
}
DAGTask getTask(String taskName) {
for (DAGTask task : tasks) { // O(N) scan
opCount++;
if (task.name.equals(taskName)) {
return task;
}
}
throw new RuntimeException("task not found: " + taskName);
}
// Simulates executeDAG: for each target task, call getTask() 3 times
// (matches the 3 GetTask calls on lines 292, 300, 307 in dag.go)
void executeDAG(List<String> targetTasks) {
for (String taskName : targetTasks) {
getTask(taskName); // line 292: task := dagCtx.GetTask(ctx, taskName)
getTask(taskName); // line 300: dagCtx.GetTask(ctx, taskName).Hooks
getTask(taskName); // line 307: dagCtx.GetTask(ctx, taskName).GetExitHook(...)
}
}
}
// -----------------------------------------------------------------------
// FIXED: tasks stored as Map<String, DAGTask>, GetTask does O(1) lookup
// -----------------------------------------------------------------------
static class FixedDagContext {
final List<DAGTask> tasks;
final Map<String, DAGTask> taskByName;
FixedDagContext(List<DAGTask> tasks) {
this.tasks = new ArrayList<>(tasks);
this.taskByName = new HashMap<>(tasks.size() * 2);
for (DAGTask t : tasks) {
this.taskByName.put(t.name, t);
}
}
DAGTask getTask(String taskName) {
opCount++; // count each lookup
DAGTask task = taskByName.get(taskName);
if (task == null) throw new RuntimeException("task not found: " + taskName);
return task;
}
void executeDAG(List<String> targetTasks) {
for (String taskName : targetTasks) {
getTask(taskName);
getTask(taskName);
getTask(taskName);
}
}
}
// Build N tasks (all as target tasks worst case: getTask scans entire list)
static List<DAGTask> buildTasks(int n) {
List<DAGTask> tasks = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
tasks.add(new DAGTask("task-" + i, Collections.emptyList()));
}
return tasks;
}
public static void main(String[] args) {
int passed = 0;
int total = 0;
// ------------------------------------------------------------------
// Test 1: Correctness both return same task
// ------------------------------------------------------------------
total++;
{
List<DAGTask> tasks = buildTasks(10);
DefectiveDagContext def = new DefectiveDagContext(tasks);
FixedDagContext fix = new FixedDagContext(tasks);
opCount = 0;
DAGTask defTask = def.getTask("task-7");
opCount = 0;
DAGTask fixTask = fix.getTask("task-7");
check("Correctness: both find task-7", defTask.name.equals("task-7") && fixTask.name.equals("task-7"));
passed++;
}
// ------------------------------------------------------------------
// Test 2: Op-count for getTask on last element defective is O(N)
// ------------------------------------------------------------------
total++;
{
int n = 100;
List<DAGTask> tasks = buildTasks(n);
DefectiveDagContext def = new DefectiveDagContext(tasks);
FixedDagContext fix = new FixedDagContext(tasks);
opCount = 0;
def.getTask("task-99"); // last element -> worst case: N comparisons
long defOps = opCount;
opCount = 0;
fix.getTask("task-99");
long fixOps = opCount;
System.out.printf(" Single getTask (last of N=%d): defective=%d ops, fixed=%d ops%n",
n, defOps, fixOps);
check("Defective getTask(last) scans all N elements", defOps == n);
check("Fixed getTask is O(1)", fixOps == 1);
passed += 2;
total++;
}
// ------------------------------------------------------------------
// Test 3: executeDAG op-count ratio O(N²) vs O(N)
// ------------------------------------------------------------------
total++;
{
int n = 300;
List<DAGTask> tasks = buildTasks(n);
List<String> targetTasks = new ArrayList<>();
for (DAGTask t : tasks) targetTasks.add(t.name);
DefectiveDagContext def = new DefectiveDagContext(tasks);
FixedDagContext fix = new FixedDagContext(tasks);
opCount = 0;
def.executeDAG(targetTasks);
long defOps = opCount;
opCount = 0;
fix.executeDAG(targetTasks);
long fixOps = opCount;
double ratio = (double) defOps / fixOps;
System.out.printf(" executeDAG N=%d: defective=%d ops, fixed=%d ops, ratio=%.1fx%n",
n, defOps, fixOps, ratio);
// Defective: 3 calls × avg N/2 scans × N tasks = 3N²/2
// Fixed: 3 calls × 1 lookup × N tasks = 3N
// Expected ratio N/2 = 150 for N=300; require >= 50x conservatively
check("Op-count ratio >= 50x for executeDAG N=" + n, ratio >= 50.0);
passed++;
}
// ------------------------------------------------------------------
// Test 4: Quadratic growth ops at N=200 should be ~4x ops at N=100
// ------------------------------------------------------------------
total++;
{
List<DAGTask> tasks100 = buildTasks(100);
List<DAGTask> tasks200 = buildTasks(200);
List<String> target100 = new ArrayList<>(); for (DAGTask t : tasks100) target100.add(t.name);
List<String> target200 = new ArrayList<>(); for (DAGTask t : tasks200) target200.add(t.name);
opCount = 0;
new DefectiveDagContext(tasks100).executeDAG(target100);
long ops100 = opCount;
opCount = 0;
new DefectiveDagContext(tasks200).executeDAG(target200);
long ops200 = opCount;
double growthRatio = (double) ops200 / ops100;
System.out.printf(" Defective growth (200 vs 100): %.2fx (expected ~4x for O(N²))%n",
growthRatio);
check("Defective shows quadratic growth (ratio >= 3.5x)", growthRatio >= 3.5);
passed++;
}
// ------------------------------------------------------------------
// Test 5: Linear growth for fixed
// ------------------------------------------------------------------
total++;
{
List<DAGTask> tasks100 = buildTasks(100);
List<DAGTask> tasks200 = buildTasks(200);
List<String> target100 = new ArrayList<>(); for (DAGTask t : tasks100) target100.add(t.name);
List<String> target200 = new ArrayList<>(); for (DAGTask t : tasks200) target200.add(t.name);
opCount = 0;
new FixedDagContext(tasks100).executeDAG(target100);
long ops100 = opCount;
opCount = 0;
new FixedDagContext(tasks200).executeDAG(target200);
long ops200 = opCount;
double growthRatio = (double) ops200 / ops100;
System.out.printf(" Fixed growth (200 vs 100): %.2fx (expected ~2x for O(N))%n",
growthRatio);
check("Fixed shows linear growth (ratio < 3.0x)", growthRatio < 3.0);
passed++;
}
System.out.printf("%n%d/%d PASS%n", passed, total);
}
}