package bench; import support.TarjanAlgorithm; import support.TarjanAlgorithm.Node; import support.TarjanAlgorithm.Result; import java.util.List; /** * Before/after timing benchmark for the Tarjan O(V²) defect. * * Uses the two self-contained implementations in TarjanAlgorithm: * BEFORE (defective): stack.contains(n) — O(V²) per graph * AFTER (fixed): n.onStack — O(V+E) per graph * * Graph topology: starWithBackEdges(V) * N0 → N1..N(v-1), N_k → N0 for k=1..v-1 * Produces exactly V*(V+1)/2-1 comparisons (defective) vs V-1 (fixed). * * Output: side-by-side timing table + speedup ratio. * * Compile and run: * cd tests * java -m jdk.compiler/com.sun.tools.javac.Main -cp . \ * support/TarjanAlgorithm.java bench/BeforeAfterBenchmark.java * java -cp . bench.BeforeAfterBenchmark */ public class BeforeAfterBenchmark { static final int WARMUP = 2_000; static final int TRIALS = 10_000; public static void main(String[] args) { System.out.println("=== Tarjan Before/After Timing Benchmark ==="); System.out.println("Graph: starWithBackEdges(V)"); System.out.println("Warmup: " + WARMUP + " iterations per size"); System.out.println("Trials: " + TRIALS + " iterations per size"); System.out.println(); printHeader(); int[] sizes = {10, 25, 50, 100, 200, 400, 800}; for (int v : sizes) { runSize(v); } System.out.println(); System.out.println("Comparison counts (exact, not timing):"); printComparisonTable(); } static void printHeader() { System.out.printf("%-6s %-14s %-14s %-10s %-12s %-12s%n", "V", "BEFORE ns/op", "AFTER ns/op", "speedup", "BEFORE cmps", "AFTER cmps"); System.out.println("-".repeat(75)); } static void runSize(int v) { // ── warmup ─────────────────────────────────────────────────────────── for (int i = 0; i < WARMUP; i++) { TarjanAlgorithm.tarjanDefective(TarjanAlgorithm.starWithBackEdges(v)); TarjanAlgorithm.tarjanFixed(TarjanAlgorithm.starWithBackEdges(v)); } // ── timed: BEFORE ──────────────────────────────────────────────────── long beforeNs = 0; for (int i = 0; i < TRIALS; i++) { List g = TarjanAlgorithm.starWithBackEdges(v); long t = System.nanoTime(); TarjanAlgorithm.tarjanDefective(g); beforeNs += System.nanoTime() - t; } // ── timed: AFTER ───────────────────────────────────────────────────── long afterNs = 0; for (int i = 0; i < TRIALS; i++) { List g = TarjanAlgorithm.starWithBackEdges(v); long t = System.nanoTime(); TarjanAlgorithm.tarjanFixed(g); afterNs += System.nanoTime() - t; } long beforePerOp = beforeNs / TRIALS; long afterPerOp = afterNs / TRIALS; double speedup = (double) beforePerOp / afterPerOp; long beforeCmps = (long) v * (v + 1) / 2 - 1; long afterCmps = v - 1; System.out.printf("%-6d %-14d %-14d %-10.2fx %-12d %-12d%n", v, beforePerOp, afterPerOp, speedup, beforeCmps, afterCmps); } static void printComparisonTable() { System.out.printf("%-6s %-14s %-14s %-10s%n", "V", "BEFORE cmps", "AFTER cmps", "ratio"); System.out.println("-".repeat(50)); int[] sizes = {10, 25, 50, 100, 200, 400, 800}; for (int v : sizes) { long before = (long) v * (v + 1) / 2 - 1; long after = v - 1; System.out.printf("%-6d %-14d %-14d %.1fx%n", v, before, after, (double) before / after); } } }