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.
201 lines
11 KiB
Java
201 lines
11 KiB
Java
package bench;
|
||
|
||
import support.PostgresqlVarDedupAlgorithm;
|
||
import support.PostgresqlVarDedupAlgorithm.Var;
|
||
import support.PostgresqlExprMembershipAlgorithm;
|
||
import support.PostgresqlExprMembershipAlgorithm.Expr;
|
||
import support.PostgresqlExprMembershipAlgorithm.EquivalenceMember;
|
||
import support.PostgresqlJoinMergeAlgorithm;
|
||
import support.PostgresqlJoinMergeAlgorithm.RelTarget;
|
||
|
||
import java.util.*;
|
||
|
||
/**
|
||
* PostgresqlBenchmark — timing benchmark for postgresql-0002, -0003, -0004.
|
||
*
|
||
* Three sites, all CWE-407 (missing visited/seen set), all fixable without
|
||
* nodeHash() when the expressions involved are pure Var nodes.
|
||
*
|
||
* 0002 preptlist.c:180,206,316 tlist_member × 3 MERGE/UPDATE/RETURNING
|
||
* 0003 equivclass.c:1041 list_member EC Var membership check
|
||
* 0004 analyzejoins.c:1914 list_member join elimination merge
|
||
*
|
||
* For each site, benchmark runs the defective (O(n²)) and fixed (O(n))
|
||
* algorithms at increasing scale and reports wall-clock time and speedup.
|
||
*
|
||
* These are ALGORITHM MICRO-BENCHMARKS, not real PostgreSQL query timings.
|
||
* Real query planning overhead includes catalog lookups, lock acquisition,
|
||
* and other work that dominates at low N. The micro-benchmark isolates the
|
||
* membership-check algorithm and represents the speedup ceiling for each site.
|
||
*/
|
||
public class PostgresqlBenchmark {
|
||
|
||
static final int WARMUP_ROUNDS = 5;
|
||
|
||
// ── 0002: preptlist.c — MERGE Var dedup ──────────────────────────────────
|
||
|
||
static void bench0002() {
|
||
System.out.println();
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.println(" postgresql-0002 — preptlist.c tlist_member (MERGE/UPDATE/RETURNING)");
|
||
System.out.println(" tlist_member O(n²) → HashSet/Bitmapset O(n)");
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.printf(" %-8s %-14s %-14s %-10s %s%n",
|
||
"N vars", "Defective (ms)", "Fixed (ms)", "Speedup", "Tlist");
|
||
System.out.println(" " + "─".repeat(62));
|
||
|
||
for (int n : new int[]{20, 50, 100, 200, 500, 1000, 2000}) {
|
||
List<Var> vars = PostgresqlVarDedupAlgorithm.buildVarPool(n, 1, n / 2);
|
||
|
||
// warmup
|
||
for (int i = 0; i < WARMUP_ROUNDS; i++) {
|
||
PostgresqlVarDedupAlgorithm.defectiveBuildTlist(vars, 1);
|
||
PostgresqlVarDedupAlgorithm.fixedBuildTlist(vars, 1);
|
||
}
|
||
|
||
long t0 = System.nanoTime();
|
||
PostgresqlVarDedupAlgorithm.Result def =
|
||
PostgresqlVarDedupAlgorithm.defectiveBuildTlist(vars, 1);
|
||
long defNs = System.nanoTime() - t0;
|
||
|
||
t0 = System.nanoTime();
|
||
PostgresqlVarDedupAlgorithm.Result fix =
|
||
PostgresqlVarDedupAlgorithm.fixedBuildTlist(vars, 1);
|
||
long fixNs = System.nanoTime() - t0;
|
||
|
||
System.out.printf(" %-8d %-14.3f %-14.3f %-10.1fx %d%n",
|
||
vars.size(),
|
||
defNs / 1e6,
|
||
fixNs / 1e6,
|
||
(double) defNs / Math.max(1, fixNs),
|
||
def.tlist.size());
|
||
}
|
||
}
|
||
|
||
// ── 0003: equivclass.c — EC member Var membership ────────────────────────
|
||
|
||
static void bench0003() {
|
||
System.out.println();
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.println(" postgresql-0003 — equivclass.c list_member (EC Var membership)");
|
||
System.out.println(" list_member O(|exprvars| × M × K) → HashSet O(|exprvars| + M × K)");
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.printf(" %-12s %-14s %-14s %s%n",
|
||
"|exprvars|", "Defective (ms)", "Fixed (ms)", "Speedup");
|
||
System.out.println(" " + "─".repeat(54));
|
||
|
||
Random rng = new Random(42);
|
||
int emMembers = 30, emVarsEach = 6;
|
||
|
||
for (int e : new int[]{10, 50, 100, 500, 1000, 2000, 5000}) {
|
||
List<Expr> exprvars = PostgresqlExprMembershipAlgorithm.buildExprList(e, 0);
|
||
List<EquivalenceMember> members =
|
||
PostgresqlExprMembershipAlgorithm.buildEcMembers(emMembers, emVarsEach, e, rng);
|
||
|
||
// warmup
|
||
for (int i = 0; i < WARMUP_ROUNDS; i++) {
|
||
PostgresqlExprMembershipAlgorithm.defectiveFindEm(exprvars, members);
|
||
PostgresqlExprMembershipAlgorithm.fixedFindEm(exprvars, members);
|
||
}
|
||
|
||
long t0 = System.nanoTime();
|
||
PostgresqlExprMembershipAlgorithm.Result def =
|
||
PostgresqlExprMembershipAlgorithm.defectiveFindEm(exprvars, members);
|
||
long defNs = System.nanoTime() - t0;
|
||
|
||
t0 = System.nanoTime();
|
||
PostgresqlExprMembershipAlgorithm.Result fix =
|
||
PostgresqlExprMembershipAlgorithm.fixedFindEm(exprvars, members);
|
||
long fixNs = System.nanoTime() - t0;
|
||
|
||
System.out.printf(" %-12d %-14.3f %-14.3f %.1fx%n",
|
||
e,
|
||
defNs / 1e6,
|
||
fixNs / 1e6,
|
||
(double) defNs / Math.max(1, fixNs));
|
||
}
|
||
}
|
||
|
||
// ── 0004: analyzejoins.c — join elimination reltarget merge ──────────────
|
||
|
||
static void bench0004() {
|
||
System.out.println();
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.println(" postgresql-0004 — analyzejoins.c list_member (join elim merge)");
|
||
System.out.println(" list_member O(N × M) → HashSet O(N + M)");
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.printf(" %-10s %-14s %-14s %s%n",
|
||
"N=M exprs", "Defective (ms)", "Fixed (ms)", "Speedup");
|
||
System.out.println(" " + "─".repeat(54));
|
||
|
||
Random rng = new Random(42);
|
||
|
||
for (int n : new int[]{10, 25, 50, 100, 200, 500, 1000}) {
|
||
int overlap = n / 2;
|
||
List<PostgresqlJoinMergeAlgorithm.Expr> keepExprs = new ArrayList<>();
|
||
for (int i = 0; i < n; i++)
|
||
keepExprs.add(new PostgresqlJoinMergeAlgorithm.Expr(i));
|
||
|
||
List<PostgresqlJoinMergeAlgorithm.Expr> removeExprs = new ArrayList<>();
|
||
for (int i = 0; i < overlap; i++)
|
||
removeExprs.add(new PostgresqlJoinMergeAlgorithm.Expr(i));
|
||
for (int i = n; i < n + (n - overlap); i++)
|
||
removeExprs.add(new PostgresqlJoinMergeAlgorithm.Expr(i));
|
||
Collections.shuffle(removeExprs, rng);
|
||
|
||
RelTarget toKeep = new RelTarget(keepExprs);
|
||
RelTarget toRemove = new RelTarget(removeExprs);
|
||
|
||
// warmup
|
||
for (int i = 0; i < WARMUP_ROUNDS; i++) {
|
||
PostgresqlJoinMergeAlgorithm.defectiveMerge(toRemove, toKeep);
|
||
PostgresqlJoinMergeAlgorithm.fixedMerge(toRemove, toKeep);
|
||
}
|
||
|
||
long t0 = System.nanoTime();
|
||
PostgresqlJoinMergeAlgorithm.Result def =
|
||
PostgresqlJoinMergeAlgorithm.defectiveMerge(toRemove, toKeep);
|
||
long defNs = System.nanoTime() - t0;
|
||
|
||
t0 = System.nanoTime();
|
||
PostgresqlJoinMergeAlgorithm.Result fix =
|
||
PostgresqlJoinMergeAlgorithm.fixedMerge(toRemove, toKeep);
|
||
long fixNs = System.nanoTime() - t0;
|
||
|
||
System.out.printf(" %-10d %-14.3f %-14.3f %.1fx%n",
|
||
n,
|
||
defNs / 1e6,
|
||
fixNs / 1e6,
|
||
(double) defNs / Math.max(1, fixNs));
|
||
}
|
||
}
|
||
|
||
// ── Main ─────────────────────────────────────────────────────────────────
|
||
|
||
public static void main(String[] args) {
|
||
System.out.println();
|
||
System.out.println("╔══════════════════════════════════════════════════════════════════╗");
|
||
System.out.println("║ PostgresqlBenchmark — CWE-407 algorithm micro-benchmarks ║");
|
||
System.out.println("║ postgresql-0002 postgresql-0003 postgresql-0004 ║");
|
||
System.out.println("╠══════════════════════════════════════════════════════════════════╣");
|
||
System.out.println("║ All three sites: list membership O(n²) → hash set O(n) ║");
|
||
System.out.println("║ Fix path B: Bitmapset/HashMap on Var identity, no nodeHash() ║");
|
||
System.out.println("║ NOTE: algorithm isolation — not real PostgreSQL query timings ║");
|
||
System.out.println("╚══════════════════════════════════════════════════════════════════╝");
|
||
|
||
bench0002();
|
||
bench0003();
|
||
bench0004();
|
||
|
||
System.out.println();
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.println(" SUMMARY");
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
System.out.println(" postgresql-0002 FIXABLE preptlist.c:180,206,316 — Path B");
|
||
System.out.println(" postgresql-0003 FIXABLE equivclass.c:1041 — Path B");
|
||
System.out.println(" postgresql-0004 FIXABLE analyzejoins.c:1914 — nodeHash()");
|
||
System.out.println(" postgresql-0001 DEFERRED tlist.c:812 — Path A");
|
||
System.out.println(" postgresql-0005 FIXABLE list.c ptr variants — Path B (ptr)");
|
||
System.out.println("══════════════════════════════════════════════════════════════════");
|
||
}
|
||
}
|