Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
107 lines
4.1 KiB
Java
107 lines
4.1 KiB
Java
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<Node> 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<Node> 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);
|
|
}
|
|
}
|
|
}
|