whitepaper: 366/178 — wave5 defect tables + PDF rebuild

This commit is contained in:
russell@unturf.com 2026-03-27 15:37:42 -04:00
parent 835ae73b0f
commit a4b0cf4edd
79 changed files with 3829 additions and 17 deletions

View file

@ -7,6 +7,7 @@ import java.util.*;
*
* mysql-0001: SHOW GRANTS USING roles — O(U*G) vector find vs O(U) hash lookup
* mysql-0002: has_global_grant fallback — O(P) multimap equal_range+find vs O(1) map lookup
* mysql-0003: setup_fields() iterator recovery — O(F²) std::find vs O(F) index loop
*
* No JUnit. Prints N/N PASS.
*/
@ -149,6 +150,55 @@ public class MysqlTest {
return new long[]{ops};
}
// -----------------------------------------------------------------------
// mysql-0003 — setup_fields iterator recovery: O(F²) std::find vs O(F) index loop
//
// Models sql/sql_base.cc:~9496
// for (auto it = fields->begin(); it != fields->end(); ++it) {
// ...split_sum_func may append items to fields...
// if (old_size != fields->size()) {
// it = std::find(fields->begin(), fields->end(), item); // O(F)
// }
// }
//
// Worst case: every item triggers split_sum_func → O(F) recovery per item → O(F²)
// Fix: use index-based loop; index is stable under append-only growth → O(F) total
// -----------------------------------------------------------------------
static long setupFieldsSlow(int F) {
List<Integer> fields = new ArrayList<>(F * 2);
for (int i = 0; i < F; i++) fields.add(i);
long ops = 0;
int limit = F; // process original F items
for (int i = 0; i < limit; i++) {
Integer item = fields.get(i);
// split_sum_func: append one new item
fields.add(-(i + 1));
// O(|fields|) std::find to re-discover current item's position
for (int j = 0; j < fields.size(); j++) {
ops++;
if (fields.get(j).equals(item)) break;
}
}
return ops;
}
static long setupFieldsFast(int F) {
List<Integer> fields = new ArrayList<>(F * 2);
for (int i = 0; i < F; i++) fields.add(i);
long ops = 0;
// Index-based loop: no re-scan needed after append
for (int idx = 0; idx < F; idx++) {
ops++; // direct indexed access — O(1)
// split_sum_func appends but doesn't affect idx
fields.add(-(idx + 1));
}
return ops;
}
// -----------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------
@ -200,6 +250,28 @@ public class MysqlTest {
if (!pass) { System.out.println(" FAIL: expected slowOps > fastOps * 10"); failures++; }
}
// --- mysql-0003: setup_fields iterator recovery ---
{
int F = 500;
long[] slowOps = new long[1], fastOps = new long[1];
Runnable slow = () -> slowOps[0] = setupFieldsSlow(F);
Runnable fast = () -> fastOps[0] = setupFieldsFast(F);
slow.run(); fast.run();
long t0 = System.nanoTime(); slow.run(); long sMs = (System.nanoTime() - t0) / 1_000_000;
long t1 = System.nanoTime(); fast.run(); long fMs = (System.nanoTime() - t1) / 1_000_000;
double speedup = fastOps[0] > 0 ? (double) slowOps[0] / fastOps[0] : 0;
System.out.printf(" %-60s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.1fx%n",
"mysql-0003 setup_fields O(F²) std::find vs O(F) index", sMs, slowOps[0], fMs, fastOps[0], speedup);
total++;
// slow: each of F items triggers O(F+i) scan → sum ~ F²/2; fast: F ops
// At F=500: slow~125000+ ops, fast=500 ops → ratio >>10x
boolean pass = slowOps[0] > fastOps[0] * 10L;
if (!pass) { System.out.printf(" FAIL mysql-0003: slowOps=%,d fastOps=%,d (expected >10x)%n", slowOps[0], fastOps[0]); failures++; }
}
System.out.println("=".repeat(100));
System.out.printf("%d/%d %s%n", total - failures, total, failures == 0 ? "PASS" : "FAIL");
if (failures > 0) System.exit(1);