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.
449 lines
18 KiB
Java
449 lines
18 KiB
Java
package bench;
|
|
|
|
import support.TarjanAlgorithm;
|
|
import support.FindNodeAlgorithm;
|
|
import support.ClosureAlgorithm;
|
|
import support.TopoSorterAlgorithm;
|
|
import support.DependencyListAlgorithm;
|
|
import support.BoundSetAlgorithm;
|
|
|
|
import unit.HiveGenMRSeenOpsTest;
|
|
import unit.SparkAnalyzerWindowAggTest;
|
|
import unit.FrroutingOspfVertexParentTest;
|
|
import unit.TorRouterlistTest;
|
|
import unit.SolcCallGraphCycleTest;
|
|
import unit.SolcAssemblyRjumpTest;
|
|
import unit.BuildkitHasLinkTest;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* Consolidated before/after benchmark for all five defects.
|
|
*
|
|
* Measures wall-clock time (ns/op) and exact operation counts for each
|
|
* defective and fixed implementation pair.
|
|
*
|
|
* Methodology:
|
|
* - 2000 warmup iterations per benchmark (JIT warm-up)
|
|
* - 10000 measurement iterations
|
|
* - Reports: ns/op, speedup multiplier, operation counts
|
|
*
|
|
* Defects covered:
|
|
* 0001 GraphUtils$Tarjan stack.contains(n) → n.onStack
|
|
* 0002a InferenceGraph.findNode ArrayList scan → HashMap
|
|
* 0002b InferenceGraph.closure uncached DFS → cached
|
|
* 0003 TopoSorter.visit Deque.contains → HashSet.contains
|
|
* 0004 DependencyList.add List.contains → LinkedHashSet.add
|
|
* 0005 InferenceContext.isEquiv List.containsAll → Set.equals
|
|
*
|
|
* No build tool required. Compile and run:
|
|
*
|
|
* cd tests
|
|
* java -m jdk.compiler/com.sun.tools.javac.Main -cp . \
|
|
* support/TarjanAlgorithm.java support/FindNodeAlgorithm.java \
|
|
* support/ClosureAlgorithm.java support/TopoSorterAlgorithm.java \
|
|
* support/DependencyListAlgorithm.java support/BoundSetAlgorithm.java \
|
|
* bench/AllDefectsBenchmark.java
|
|
* java -cp . bench.AllDefectsBenchmark
|
|
*/
|
|
public class AllDefectsBenchmark {
|
|
|
|
private static final int WARMUP = 2_000;
|
|
private static final int ITERATIONS = 10_000;
|
|
|
|
public static void main(String[] args) {
|
|
System.out.println("=== All-Defects Benchmark: Before vs After ===\n");
|
|
System.out.println("Warmup: " + WARMUP + " iters | Measurement: " + ITERATIONS + " iters\n");
|
|
|
|
System.out.printf("%-6s %-30s %12s %12s %8s %12s %12s%n",
|
|
"TICKET", "DEFECT", "BEFORE ns/op", "AFTER ns/op", "SPEEDUP",
|
|
"BEFORE cmps", "AFTER cmps");
|
|
System.out.println("-".repeat(100));
|
|
|
|
bench0001();
|
|
bench0002a();
|
|
bench0002b();
|
|
bench0003();
|
|
bench0004();
|
|
bench0005();
|
|
|
|
System.out.println();
|
|
benchHive();
|
|
benchSpark();
|
|
benchFrrouting();
|
|
benchTor();
|
|
benchSolc0001();
|
|
benchSolc0002();
|
|
benchBuildkit();
|
|
|
|
System.out.println("\nDone.");
|
|
}
|
|
|
|
// ─── 0001: Tarjan stack.contains vs n.onStack ────────────────────────────
|
|
|
|
static void bench0001() {
|
|
int v = 200;
|
|
|
|
// Warmup
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
TarjanAlgorithm.tarjanDefective(TarjanAlgorithm.starWithBackEdges(v));
|
|
TarjanAlgorithm.tarjanFixed(TarjanAlgorithm.starWithBackEdges(v));
|
|
}
|
|
|
|
// Measure defective
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
TarjanAlgorithm.Result r = TarjanAlgorithm.tarjanDefective(TarjanAlgorithm.starWithBackEdges(v));
|
|
defCmps = r.comparisons;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
// Measure fixed
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
TarjanAlgorithm.Result r = TarjanAlgorithm.tarjanFixed(TarjanAlgorithm.starWithBackEdges(v));
|
|
fixCmps = r.comparisons;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0001", "Tarjan stack.contains(n) V=" + v,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── 0002a: findNode ArrayList scan vs HashMap ───────────────────────────
|
|
|
|
static void bench0002a() {
|
|
int n = 200;
|
|
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
FindNodeAlgorithm.queryAllDefective(n);
|
|
FindNodeAlgorithm.queryAllFixed(n);
|
|
}
|
|
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
defCmps = FindNodeAlgorithm.queryAllDefective(n).comparisons;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
fixCmps = FindNodeAlgorithm.queryAllFixed(n).comparisons;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0002a", "findNode ArrayList scan N=" + n,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── 0002b: closure uncached DFS vs cached ────────────────────────────────
|
|
|
|
static void bench0002b() {
|
|
int v = 100, k = 100;
|
|
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
ClosureAlgorithm.closureDefective(ClosureAlgorithm.buildLinearChain(v), k);
|
|
ClosureAlgorithm.closureFixed(ClosureAlgorithm.buildLinearChain(v), k);
|
|
}
|
|
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
defCmps = ClosureAlgorithm.closureDefective(
|
|
ClosureAlgorithm.buildLinearChain(v), k).nodeVisits;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
fixCmps = ClosureAlgorithm.closureFixed(
|
|
ClosureAlgorithm.buildLinearChain(v), k).nodeVisits;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0002b", "closure uncached DFS V=" + v + " K=" + k,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── 0003: TopoSorter Deque.contains vs HashSet ──────────────────────────
|
|
|
|
static void bench0003() {
|
|
int v = 200;
|
|
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
TopoSorterAlgorithm.topoSortDefective(TopoSorterAlgorithm.buildLinearChain(v));
|
|
TopoSorterAlgorithm.topoSortFixed(TopoSorterAlgorithm.buildLinearChain(v));
|
|
}
|
|
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
defCmps = TopoSorterAlgorithm.topoSortDefective(
|
|
TopoSorterAlgorithm.buildLinearChain(v)).comparisons;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
fixCmps = TopoSorterAlgorithm.topoSortFixed(
|
|
TopoSorterAlgorithm.buildLinearChain(v)).comparisons;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0003", "TopoSorter Deque.contains V=" + v,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── 0004: DependencyList List.contains vs LinkedHashSet ─────────────────
|
|
|
|
static void bench0004() {
|
|
int m = 200;
|
|
int[] items = DependencyListAlgorithm.buildUniqueSequence(m);
|
|
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
DependencyListAlgorithm.addUniqueItemsDefective(items);
|
|
DependencyListAlgorithm.addUniqueItemsFixed(items);
|
|
}
|
|
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
defCmps = DependencyListAlgorithm.addUniqueItemsDefective(items).comparisons;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
fixCmps = DependencyListAlgorithm.addUniqueItemsFixed(items).comparisons;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0004", "DependencyList.add contains M=" + m,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── 0005: BoundSet List.containsAll vs Set.equals ───────────────────────
|
|
|
|
static void bench0005() {
|
|
int b = 100;
|
|
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
BoundSetAlgorithm.isEquivDefective(
|
|
BoundSetAlgorithm.buildForwardList(b),
|
|
BoundSetAlgorithm.buildReversedList(b));
|
|
BoundSetAlgorithm.isEquivFixed(
|
|
BoundSetAlgorithm.buildForwardList(b),
|
|
BoundSetAlgorithm.buildReversedList(b));
|
|
}
|
|
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
defCmps = BoundSetAlgorithm.isEquivDefective(
|
|
BoundSetAlgorithm.buildForwardList(b),
|
|
BoundSetAlgorithm.buildReversedList(b)).comparisons;
|
|
}
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++) {
|
|
fixCmps = BoundSetAlgorithm.isEquivFixed(
|
|
BoundSetAlgorithm.buildForwardList(b),
|
|
BoundSetAlgorithm.buildReversedList(b)).comparisons;
|
|
}
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("0005", "BoundSet containsAll B=" + b,
|
|
defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── hive-0001/0002: ArrayList→HashSet seenOps ───────────────────────────
|
|
|
|
static void benchHive() {
|
|
int t = 100;
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
HiveGenMRSeenOpsTest.simulateDefective(t);
|
|
HiveGenMRSeenOpsTest.simulateFixed(t);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = HiveGenMRSeenOpsTest.simulateDefective(t);
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = HiveGenMRSeenOpsTest.simulateFixed(t);
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("hive", "GenMRProcContext seenOps T=" + t, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── spark-0001: ArrayBuffer→LinkedHashSet seenWindowAggregates ──────────
|
|
|
|
static void benchSpark() {
|
|
int n = 100;
|
|
List<SparkAnalyzerWindowAggTest.AggExpr> wins = SparkAnalyzerWindowAggTest.windowAggs(n);
|
|
List<SparkAnalyzerWindowAggTest.AggExpr> aggs = SparkAnalyzerWindowAggTest.otherAggs(n, wins);
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
SparkAnalyzerWindowAggTest.extractDefective(wins, aggs);
|
|
SparkAnalyzerWindowAggTest.extractFixed(wins, aggs);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = SparkAnalyzerWindowAggTest.extractDefective(wins, aggs).comparisons;
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = SparkAnalyzerWindowAggTest.extractFixed(wins, aggs).comparisons;
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("spark", "Analyzer seenWindowAggs W=A=" + n, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── frrouting-0002: listnode_lookup→hash in Dijkstra ────────────────────
|
|
|
|
static void benchFrrouting() {
|
|
int v = 200;
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
FrroutingOspfVertexParentTest.addParentDefective(v);
|
|
FrroutingOspfVertexParentTest.addParentFixed(v);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = FrroutingOspfVertexParentTest.addParentDefective(v).comparisons;
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = FrroutingOspfVertexParentTest.addParentFixed(v).comparisons;
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("frrout", "ospf_vertex_add_parent V=" + v, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── tor-0001: smartlist_contains_string→digestset ───────────────────────
|
|
|
|
@SuppressWarnings("unchecked")
|
|
static void benchTor() {
|
|
int r = 800;
|
|
Object[] fixtures = TorRouterlistTest.buildFixtures(r, 0);
|
|
List<String> req = (List<String>) fixtures[0];
|
|
List<String> recv = (List<String>) fixtures[1];
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
TorRouterlistTest.processDefective(req, recv);
|
|
TorRouterlistTest.processFixed(req, recv);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = TorRouterlistTest.processDefective(req, recv).comparisons;
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = TorRouterlistTest.processFixed(req, recv).comparisons;
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("tor", "routerlist fingerprints R=" + r, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── solc-0001: std::find currentPath→unordered_set ──────────────────────
|
|
|
|
static void benchSolc0001() {
|
|
int f = 64, d = 64;
|
|
Map<String, List<String>> g = SolcCallGraphCycleTest.chainGraph(f, d);
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
SolcCallGraphCycleTest.simulateDefective(g);
|
|
SolcCallGraphCycleTest.simulateFixed(g);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = SolcCallGraphCycleTest.simulateDefective(g);
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = SolcCallGraphCycleTest.simulateFixed(g);
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("solc1", "CallGraphCycleFinder F=D=" + f, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── solc-0002: std::find items→unordered_map index ──────────────────────
|
|
|
|
static void benchSolc0002() {
|
|
int j = 500, n = 500;
|
|
for (int i = 0; i < WARMUP; i++) {
|
|
SolcAssemblyRjumpTest.simulateDefective(j, n);
|
|
SolcAssemblyRjumpTest.simulateFixed(j, n);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
defCmps = SolcAssemblyRjumpTest.simulateDefective(j, n);
|
|
long defNs = (System.nanoTime() - startDef) / ITERATIONS;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < ITERATIONS; i++)
|
|
fixCmps = SolcAssemblyRjumpTest.simulateFixed(j, n);
|
|
long fixNs = (System.nanoTime() - startFix) / ITERATIONS;
|
|
|
|
printRow("solc2", "Assembly RJUMP J=N=" + j, defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── buildkit-0001: slices.Contains→map[string]struct{} ──────────────────
|
|
// Note: simulate() includes storage construction; key metric is comparison counts.
|
|
|
|
static void benchBuildkit() {
|
|
int k = 50, l = 50;
|
|
int iters = 500; // fewer iters — string allocation dominates at larger K*L
|
|
for (int i = 0; i < 200; i++) {
|
|
BuildkitHasLinkTest.simulateDefective(k, l);
|
|
BuildkitHasLinkTest.simulateFixedQuery(k, l);
|
|
}
|
|
long startDef = System.nanoTime();
|
|
long defCmps = 0;
|
|
for (int i = 0; i < iters; i++)
|
|
defCmps = BuildkitHasLinkTest.simulateDefective(k, l);
|
|
long defNs = (System.nanoTime() - startDef) / iters;
|
|
|
|
long startFix = System.nanoTime();
|
|
long fixCmps = 0;
|
|
for (int i = 0; i < iters; i++)
|
|
fixCmps = BuildkitHasLinkTest.simulateFixedQuery(k, l);
|
|
long fixNs = (System.nanoTime() - startFix) / iters;
|
|
|
|
printRow("bkit", "HasLink K=L=" + k + " cmps>>", defNs, fixNs, defCmps, fixCmps);
|
|
}
|
|
|
|
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
|
|
static void printRow(String ticket, String label,
|
|
long defNs, long fixNs,
|
|
long defCmps, long fixCmps) {
|
|
double speedup = fixNs > 0 ? (double) defNs / fixNs : Double.NaN;
|
|
System.out.printf("%-6s %-30s %12d %12d %7.1fx %12d %12d%n",
|
|
ticket, label, defNs, fixNs, speedup, defCmps, fixCmps);
|
|
}
|
|
}
|