whitepaper: 398/185 — wave6d (rails-0012..16, jsc-0001/2, vtk, sm-0002, redis/valkey-0003, helm-0002/3, k8s-0003)
This commit is contained in:
parent
eb9612e4bf
commit
3735145aa5
47 changed files with 3488 additions and 33 deletions
|
|
@ -2,7 +2,7 @@ package unit;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* RedisTest — CWE-407 benchmarks for redis-0001 and redis-0002
|
||||
* RedisTest — CWE-407 benchmarks for redis-0001, redis-0002, redis-0003
|
||||
*
|
||||
* redis-0001: SINTER on listpack-encoded sets
|
||||
* SLOW: O(N×M) — outer iterate N elements, inner lpFind O(M) per probe set
|
||||
|
|
@ -11,6 +11,10 @@ import java.util.*;
|
|||
* redis-0002: getUpcomingChannelList ACL channel superset check
|
||||
* SLOW: O((S×C)²) — build flat list, listSearchKey O(n) per pattern
|
||||
* FAST: O(S×C) — build HashSet, O(1) lookup per pattern
|
||||
*
|
||||
* redis-0003: ACLSetSelector key-pattern/channel deduplication O(P²)
|
||||
* SLOW: O(P²) — listSearchKey(selector->patterns, newpat) called per rule
|
||||
* FAST: O(P) — parallel dict for O(1) dedup per rule
|
||||
*/
|
||||
public class RedisTest {
|
||||
|
||||
|
|
@ -100,6 +104,56 @@ public class RedisTest {
|
|||
return ops;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// redis-0003: ACLSetSelector key-pattern deduplication O(P²)
|
||||
//
|
||||
// Models ACLSetSelector: each ~<pattern> rule calls listSearchKey on the
|
||||
// already-accumulated patterns list to avoid duplicates.
|
||||
// Adding P patterns costs O(1+2+...+P) = O(P²).
|
||||
//
|
||||
// SLOW: List-based dedup (mirrors listSearchKey scan)
|
||||
// FAST: HashSet-based dedup (mirrors dict lookup fix)
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* Simulate adding P distinct key patterns to selector->patterns using
|
||||
* listSearchKey-style linear scan for deduplication.
|
||||
* Returns total number of comparisons performed.
|
||||
*/
|
||||
static long aclPatternDedup_slow(int numPatterns) {
|
||||
List<String> patterns = new ArrayList<>();
|
||||
long ops = 0;
|
||||
for (int i = 0; i < numPatterns; i++) {
|
||||
String newpat = "key:" + i;
|
||||
// listSearchKey: O(patterns.size()) scan
|
||||
boolean found = false;
|
||||
for (String p : patterns) {
|
||||
ops++;
|
||||
if (p.equals(newpat)) { found = true; break; }
|
||||
}
|
||||
if (!found) patterns.add(newpat);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate adding P distinct key patterns using a parallel dict for O(1) dedup.
|
||||
* Returns total number of comparisons performed.
|
||||
*/
|
||||
static long aclPatternDedup_fast(int numPatterns) {
|
||||
List<String> patterns = new ArrayList<>();
|
||||
Set<String> patternsHt = new HashSet<>();
|
||||
long ops = 0;
|
||||
for (int i = 0; i < numPatterns; i++) {
|
||||
String newpat = "key:" + i;
|
||||
ops++; // O(1) dict lookup
|
||||
if (patternsHt.add(newpat)) {
|
||||
patterns.add(newpat);
|
||||
}
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Main
|
||||
// =========================================================================
|
||||
|
|
@ -248,6 +302,54 @@ public class RedisTest {
|
|||
if (ok) passed++;
|
||||
}
|
||||
|
||||
// --- redis-0003 Scenario 1: P=500 distinct key patterns ---
|
||||
{
|
||||
int P = 500;
|
||||
final long[] sOps = {0}, fOps = {0};
|
||||
Runnable slow = () -> {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < 200; r++) ops += aclPatternDedup_slow(P);
|
||||
sOps[0] = ops;
|
||||
};
|
||||
Runnable fast = () -> {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < 200; r++) ops += aclPatternDedup_fast(P);
|
||||
fOps[0] = ops;
|
||||
};
|
||||
slow.run(); fast.run();
|
||||
bench("redis-0003 ACL key-pattern dedup P=500 (200 runs)", slow, fast, sOps[0], fOps[0]);
|
||||
total++;
|
||||
// P=500: slow = sum(0..499) * 200 = 24,950,000; fast = 500*200 = 100,000 → ~249x
|
||||
boolean ok = sOps[0] >= fOps[0] * 100;
|
||||
System.out.printf(" [%s] slow=%,d fast=%,d ratio=%.0fx (need >=100x)%n",
|
||||
ok ? "PASS" : "FAIL", sOps[0], fOps[0], (double) sOps[0] / fOps[0]);
|
||||
if (ok) passed++;
|
||||
}
|
||||
|
||||
// --- redis-0003 Scenario 2: P=1000 distinct key patterns ---
|
||||
{
|
||||
int P = 1000;
|
||||
final long[] sOps = {0}, fOps = {0};
|
||||
Runnable slow = () -> {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < 50; r++) ops += aclPatternDedup_slow(P);
|
||||
sOps[0] = ops;
|
||||
};
|
||||
Runnable fast = () -> {
|
||||
long ops = 0;
|
||||
for (int r = 0; r < 50; r++) ops += aclPatternDedup_fast(P);
|
||||
fOps[0] = ops;
|
||||
};
|
||||
slow.run(); fast.run();
|
||||
bench("redis-0003 ACL key-pattern dedup P=1000 (50 runs)", slow, fast, sOps[0], fOps[0]);
|
||||
total++;
|
||||
// P=1000: slow = sum(0..999) * 50 = 24,975,000; fast = 1000*50 = 50,000 → ~499x
|
||||
boolean ok = sOps[0] >= fOps[0] * 200;
|
||||
System.out.printf(" [%s] slow=%,d fast=%,d ratio=%.0fx (need >=200x)%n",
|
||||
ok ? "PASS" : "FAIL", sOps[0], fOps[0], (double) sOps[0] / fOps[0]);
|
||||
if (ok) passed++;
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
System.out.printf("%d/%d PASS%n", passed, total);
|
||||
if (passed < total) System.exit(1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue