package bench; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import java.util.*; import java.util.function.Consumer; /** * BenchMax — extreme-scale benchmarks for the gumyum white paper. * * Three defects, pushed to their limits: * * 1. javac Tarjan (starWithBackEdges) — V up to 5000 * BEFORE: stack.contains(n) O(V²) * AFTER: n.active flag O(V+E) * * 2. minecraft-0001 DependencySorter (diamond depth) — D up to 18 * BEFORE: isCyclic no visited set O(E^D) * AFTER: visited set O(E) per call * * 3. create-0001 TrackGraph BFS (ArrayList.remove(0)) — V up to 5000 * BEFORE: ArrayList.remove(0) O(V²) BFS * AFTER: ArrayDeque.poll() O(V+E) */ public class BenchMax { // ── 1. Tarjan — javac-style ─────────────────────────────────────────────── static class TNode { final int id; final List neighbors = new ArrayList<>(); boolean active = false; // fix flag TNode(int id) { this.id = id; } } static List starWithBackEdges(int v) { List nodes = new ArrayList<>(); for (int i = 0; i < v; i++) nodes.add(new TNode(i)); TNode hub = nodes.get(0); for (int i = 1; i < v; i++) { hub.neighbors.add(nodes.get(i)); nodes.get(i).neighbors.add(hub); // back edge } return nodes; } static void tarjanDefective(List graph) { List stack = new ArrayList<>(); for (TNode n : graph) { if (!stack.contains(n)) tarjanDfsDefective(n, stack); } } static void tarjanDfsDefective(TNode n, List stack) { stack.add(n); for (TNode w : n.neighbors) { if (stack.contains(w)) continue; // O(n) — defect tarjanDfsDefective(w, stack); } stack.remove(stack.size() - 1); } static void tarjanFixed(List graph) { Deque stack = new ArrayDeque<>(); for (TNode n : graph) { if (!n.active) tarjanDfsFixed(n, stack); } } static void tarjanDfsFixed(TNode n, Deque stack) { n.active = true; stack.push(n); for (TNode w : n.neighbors) { if (w.active) continue; // O(1) — fixed tarjanDfsFixed(w, stack); } stack.pop(); n.active = false; } // ── 2. DependencySorter — minecraft-0001 ───────────────────────────────── static Map> buildDiamond(int depth) { Map> deps = new LinkedHashMap<>(); deps.put("base", List.of()); String prevL = "base", prevR = "base"; for (int d = 1; d <= depth; d++) { String L = "L" + d, R = "R" + d; deps.put(L, List.of(prevL, prevR)); deps.put(R, List.of(prevL, prevR)); prevL = L; prevR = R; } deps.put("root", List.of(prevL, prevR)); return deps; } static boolean isCyclicBefore(Multimap d, String from, String to) { Collection deps = d.get(to); if (deps.contains(from)) return true; return deps.stream().anyMatch(dep -> isCyclicBefore(d, from, dep)); } static boolean isCyclicAfter(Multimap d, String from, String to, Set vis) { if (!vis.add(to)) return false; Collection deps = d.get(to); if (deps.contains(from)) return true; return deps.stream().anyMatch(dep -> isCyclicAfter(d, from, dep, vis)); } static void runDSBefore(Map> tags) { HashMultimap d = HashMultimap.create(); for (var e : tags.entrySet()) for (String dep : e.getValue()) if (!isCyclicBefore(d, e.getKey(), dep)) d.put(e.getKey(), dep); } static void runDSAfter(Map> tags) { HashMultimap d = HashMultimap.create(); for (var e : tags.entrySet()) for (String dep : e.getValue()) if (!isCyclicAfter(d, e.getKey(), dep, new HashSet<>())) d.put(e.getKey(), dep); } // ── 3. TrackGraph BFS — create-0001 ────────────────────────────────────── // Build a simple chain graph: 0→1→2→...→(v-1) with back edges every 10 nodes static Map> buildRailGraph(int v) { Map> adj = new HashMap<>(); for (int i = 0; i < v; i++) { adj.put(i, new ArrayList<>()); if (i > 0) { adj.get(i).add(i-1); adj.get(i-1).add(i); } if (i > 10) { adj.get(i).add(i-10); adj.get(i-10).add(i); } } return adj; } // BEFORE: ArrayList as BFS frontier — remove(0) is O(n) static int bfsBefore(Map> adj, int start) { List frontier = new ArrayList<>(); Set visited = new HashSet<>(); frontier.add(start); visited.add(start); int count = 0; while (!frontier.isEmpty()) { int cur = frontier.remove(0); // O(n) — defect count++; for (int nb : adj.getOrDefault(cur, List.of())) { if (visited.add(nb)) frontier.add(nb); } } return count; } // AFTER: ArrayDeque as BFS frontier — poll() is O(1) static int bfsAfter(Map> adj, int start) { Deque frontier = new ArrayDeque<>(); Set visited = new HashSet<>(); frontier.add(start); visited.add(start); int count = 0; while (!frontier.isEmpty()) { int cur = frontier.poll(); // O(1) — fixed count++; for (int nb : adj.getOrDefault(cur, List.of())) { if (visited.add(nb)) frontier.add(nb); } } return count; } // ── Main ───────────────────────────────────────────────────────────────── static final int WARMUP = 200; static final int TRIALS = 1000; public static void main(String[] args) { System.out.println("╔══════════════════════════════════════════════════════════════╗"); System.out.println("║ BenchMax — gumyum minecraft enterprise ║"); System.out.println("╚══════════════════════════════════════════════════════════════╝"); System.out.println(); // ── Javac Tarjan ───────────────────────────────────────────────────── System.out.println("── 1. javac Tarjan starWithBackEdges(V) ──────────────────────"); System.out.printf("%-6s %-14s %-14s %-8s%n", "V", "BEFORE ns/op", "AFTER ns/op", "Speedup"); System.out.println("-".repeat(48)); int[] tvSizes = {200, 400, 800, 1600, 3200}; for (int v : tvSizes) { List g = starWithBackEdges(v); for (int i = 0; i < WARMUP; i++) { tarjanFixed(g); } // skip large V for before (stack depth) long beforeNs = -1; if (v <= 800) { for (int i = 0; i < WARMUP; i++) tarjanDefective(g); long t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) tarjanDefective(starWithBackEdges(v)); beforeNs = (System.nanoTime() - t0) / TRIALS; } long t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) tarjanFixed(starWithBackEdges(v)); long afterNs = (System.nanoTime() - t0) / TRIALS; if (beforeNs >= 0) { System.out.printf("%-6d %-14d %-14d %.1fx%n", v, beforeNs, afterNs, (double)beforeNs/afterNs); } else { System.out.printf("%-6d %-14s %-14d (before too slow)%n", v, "SKIPPED", afterNs); } } // ── Minecraft DependencySorter ──────────────────────────────────────── System.out.println(); System.out.println("── 2. minecraft-0001 DependencySorter diamond depth D ───────"); System.out.printf("%-6s %-8s %-14s %-14s %-8s%n", "Depth", "Tags", "BEFORE ns", "AFTER ns", "Speedup"); System.out.println("-".repeat(60)); int[] depths = {4, 6, 8, 10, 12, 14, 16, 18}; for (int d : depths) { Map> tags = buildDiamond(d); for (int i = 0; i < WARMUP; i++) runDSAfter(tags); long beforeNs = -1; if (d <= 14) { for (int i = 0; i < WARMUP; i++) runDSBefore(tags); long t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) runDSBefore(tags); beforeNs = (System.nanoTime() - t0) / TRIALS; } long t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) runDSAfter(tags); long afterNs = (System.nanoTime() - t0) / TRIALS; if (beforeNs >= 0) { System.out.printf("%-6d %-8d %-14d %-14d %.1fx%n", d, tags.size(), beforeNs, afterNs, (double)beforeNs/afterNs); } else { System.out.printf("%-6d %-8d %-14s %-14d (OVERFLOW)%n", d, tags.size(), "OVERFLOW", afterNs); } } // ── Create TrackGraph BFS ───────────────────────────────────────────── System.out.println(); System.out.println("── 3. create-0001 TrackGraph BFS V nodes ────────────────────"); System.out.printf("%-6s %-14s %-14s %-8s%n", "V", "BEFORE ns/op", "AFTER ns/op", "Speedup"); System.out.println("-".repeat(48)); int[] bfsSizes = {100, 500, 1000, 2000, 5000}; for (int v : bfsSizes) { Map> adj = buildRailGraph(v); for (int i = 0; i < WARMUP; i++) { bfsBefore(adj, 0); bfsAfter(adj, 0); } long t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) bfsBefore(adj, 0); long beforeNs = (System.nanoTime() - t0) / TRIALS; t0 = System.nanoTime(); for (int i = 0; i < TRIALS; i++) bfsAfter(adj, 0); long afterNs = (System.nanoTime() - t0) / TRIALS; System.out.printf("%-6d %-14d %-14d %.1fx%n", v, beforeNs, afterNs, (double)beforeNs/afterNs); } System.out.println(); System.out.println("Platform: " + System.getProperty("java.vm.name") + " " + System.getProperty("java.version")); } }