mysql+proxysql: 5-MOAD scan; mysql-0005 CWE-407 row0sel template_col O(T*C) per row 31.5x, proxysql-0002 CWE-407 FTS indexed_cols O(R*C*I) 7.8x
This commit is contained in:
parent
decacb5dbd
commit
7822bb0e85
6 changed files with 437 additions and 0 deletions
92
defects/proxysql/test/ProxySQLFTSIndexedColsTest.java
Normal file
92
defects/proxysql/test/ProxySQLFTSIndexedColsTest.java
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test for proxysql-0002: MySQL_FTS indexed_cols O(R*C*I) linear scan.
|
||||
*
|
||||
* Simulates ProxySQL's MySQL_FTS::index_table() inner loop:
|
||||
* for each of R rows, for each of C columns, std::find on indexed_cols vector of I entries.
|
||||
* Fix: replace vector<string> with unordered_set<string> for O(1) membership test.
|
||||
*/
|
||||
public class ProxySQLFTSIndexedColsTest {
|
||||
|
||||
// --- DEFECTIVE: vector linear scan per column per row ---
|
||||
static long ftsIndexSlow(int rows, int cols, List<String> indexedCols) {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
String colName = "col_" + c;
|
||||
// std::find equivalent — O(I) scan
|
||||
for (String ic : indexedCols) {
|
||||
ops++;
|
||||
if (ic.equals(colName)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// --- PATCHED: unordered_set O(1) lookup per column per row ---
|
||||
static long ftsIndexFast(int rows, int cols, Set<String> indexedColsSet) {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < rows; r++) {
|
||||
for (int c = 0; c < cols; c++) {
|
||||
String colName = "col_" + c;
|
||||
ops++; // O(1) hash lookup
|
||||
boolean found = indexedColsSet.contains(colName);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("proxysql-0002: MySQL_FTS indexed_cols O(R*C*I) benchmark");
|
||||
System.out.println("=".repeat(80));
|
||||
|
||||
int failures = 0;
|
||||
int total = 0;
|
||||
|
||||
// R=5000 rows, C=20 columns, I=10 indexed columns (half of cols are indexed)
|
||||
int ROWS = 5000;
|
||||
int COLS = 20;
|
||||
int INDEXED = 10;
|
||||
|
||||
// Build indexed_cols: first INDEXED column names
|
||||
List<String> indexedColsList = new ArrayList<>();
|
||||
Set<String> indexedColsSet = new HashSet<>();
|
||||
for (int i = 0; i < INDEXED; i++) {
|
||||
String name = "col_" + i;
|
||||
indexedColsList.add(name);
|
||||
indexedColsSet.add(name);
|
||||
}
|
||||
|
||||
long[] slowOps = new long[1], fastOps = new long[1];
|
||||
Runnable slow = () -> slowOps[0] = ftsIndexSlow(ROWS, COLS, indexedColsList);
|
||||
Runnable fast = () -> fastOps[0] = ftsIndexFast(ROWS, COLS, indexedColsSet);
|
||||
|
||||
// Warmup
|
||||
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(" %-58s slow:%4dms (%,d ops) fast:%4dms (%,d ops) speedup:%.1fx%n",
|
||||
"proxysql-0002 FTS indexed_cols O(R*C*I) vs O(R*C)", sMs, slowOps[0], fMs, fastOps[0], speedup);
|
||||
|
||||
total++;
|
||||
// slow: R * C * I (worst case each col scans all I); fast: R * C
|
||||
// At R=5000, C=20, I=10: slow=1,000,000 ops, fast=100,000 ops -> 10x ratio
|
||||
boolean pass = slowOps[0] > fastOps[0] * 5L;
|
||||
if (!pass) {
|
||||
System.out.printf(" FAIL proxysql-0002: slowOps=%,d fastOps=%,d (expected >5x)%n",
|
||||
slowOps[0], fastOps[0]);
|
||||
failures++;
|
||||
} else {
|
||||
System.out.println(" PASS proxysql-0002");
|
||||
}
|
||||
|
||||
System.out.println("=".repeat(80));
|
||||
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