whitepaper: re-add 10 missing entries + 11 new defects this session, count 578→590; rebuild PDF
This commit is contained in:
parent
e4ee168b1e
commit
2e4f7807d5
401 changed files with 3914 additions and 114 deletions
|
|
@ -8,6 +8,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
|
||||
* mysql-0004: dict_index_find_and_set_cols() col_added — O(F²) std::find vs O(F) unordered_set
|
||||
*
|
||||
* No JUnit. Prints N/N PASS.
|
||||
*/
|
||||
|
|
@ -199,6 +200,66 @@ public class MysqlTest {
|
|||
return ops;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// mysql-0004 — dict_index_find_and_set_cols: O(F²) col_added vector dedup
|
||||
//
|
||||
// Models storage/innobase/dict/dict0dict.cc:dict_index_find_and_set_cols():
|
||||
// std::vector<ulint> col_added;
|
||||
// for (ulint i = 0; i < index->n_fields; i++) {
|
||||
// for (j = 0; j < table->n_cols; j++) {
|
||||
// if name matches {
|
||||
// bool exists = std::find(col_added.begin(), col_added.end(), j)
|
||||
// != col_added.end(); // O(|col_added|) = O(i)
|
||||
// if exists: goto dup_err;
|
||||
// col_added.push_back(j); // col_added grows
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// F index fields: 0+1+...+(F-1) = O(F²) total comparison ops.
|
||||
// Fix: std::unordered_set<ulint> → O(1) per lookup → O(F) total.
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Simulate dict_index_find_and_set_cols with O(F²) std::find duplicate check.
|
||||
* F = number of index fields (all distinct columns, no duplicates).
|
||||
* Returns total comparison operations.
|
||||
*/
|
||||
static long dictIndexColAddedSlow(int F) {
|
||||
List<Integer> colAdded = new ArrayList<>(F);
|
||||
long ops = 0;
|
||||
for (int i = 0; i < F; i++) {
|
||||
int colIdx = i; // each field maps to a distinct column
|
||||
// std::find: O(|col_added|) scan
|
||||
boolean exists = false;
|
||||
for (Integer c : colAdded) {
|
||||
ops++;
|
||||
if (c.equals(colIdx)) { exists = true; break; }
|
||||
}
|
||||
if (!exists) {
|
||||
colAdded.add(colIdx);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixed version: unordered_set for O(1) duplicate detection.
|
||||
* Models replacing std::vector + std::find with std::unordered_set.
|
||||
*/
|
||||
static long dictIndexColAddedFast(int F) {
|
||||
Set<Integer> colAdded = new HashSet<>(F * 2);
|
||||
long ops = 0;
|
||||
for (int i = 0; i < F; i++) {
|
||||
int colIdx = i;
|
||||
ops++; // O(1) hash lookup
|
||||
if (!colAdded.contains(colIdx)) {
|
||||
colAdded.add(colIdx);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Main
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
@ -272,6 +333,29 @@ public class MysqlTest {
|
|||
if (!pass) { System.out.printf(" FAIL mysql-0003: slowOps=%,d fastOps=%,d (expected >10x)%n", slowOps[0], fastOps[0]); failures++; }
|
||||
}
|
||||
|
||||
// --- mysql-0004: dict_index_find_and_set_cols col_added O(F²) ---
|
||||
{
|
||||
int F = 200;
|
||||
long[] slowOps = new long[1], fastOps = new long[1];
|
||||
|
||||
Runnable slow = () -> slowOps[0] = dictIndexColAddedSlow(F);
|
||||
Runnable fast = () -> fastOps[0] = dictIndexColAddedFast(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-0004 dict_index_col_added O(F²) vs O(F)", sMs, slowOps[0], fMs, fastOps[0], speedup);
|
||||
|
||||
total++;
|
||||
// At F=200: slow=0+1+...+199=19900 ops; fast=200 ops → ratio >50x
|
||||
boolean pass = slowOps[0] > fastOps[0] * 50L;
|
||||
if (!pass) { System.out.printf(" FAIL mysql-0004: slowOps=%,d fastOps=%,d (expected >50x)%n",
|
||||
slowOps[0], fastOps[0]); failures++; }
|
||||
else System.out.println(" PASS mysql-0004");
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue