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
90
defects/pulsar/unit/PulsarPartialRoundRobinRouterTest.java
Normal file
90
defects/pulsar/unit/PulsarPartialRoundRobinRouterTest.java
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
package unit;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* pulsar-0005 — PartialRoundRobinMessageRouterImpl CopyOnWriteArrayList.contains O(N×L) → HashSet O(N)
|
||||
*
|
||||
* The hot path in getOrCreatePartialList() is the filter lambda:
|
||||
* .filter(e -> !partialList.contains(e))
|
||||
*
|
||||
* This benchmark isolates the membership test — N calls to contains()
|
||||
* over a CopyOnWriteArrayList of size L vs a HashSet snapshot.
|
||||
*
|
||||
* SLOW: CopyOnWriteArrayList.contains(e) → O(L) per call → O(N × L) total
|
||||
* FAST: HashSet.contains(e) → O(1) per call → O(N) total
|
||||
*/
|
||||
public class PulsarPartialRoundRobinRouterTest {
|
||||
|
||||
static long benchSlow(int N, int L) {
|
||||
CopyOnWriteArrayList<Integer> partialList = new CopyOnWriteArrayList<>();
|
||||
for (int i = 0; i < L; i++) {
|
||||
partialList.add(i * 2); // even indices present
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
int found = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (!partialList.contains(i)) found++; // O(L) per call
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
static long benchFast(int N, int L) {
|
||||
CopyOnWriteArrayList<Integer> partialList = new CopyOnWriteArrayList<>();
|
||||
for (int i = 0; i < L; i++) {
|
||||
partialList.add(i * 2);
|
||||
}
|
||||
// FIX: snapshot to HashSet before the filter loop
|
||||
Set<Integer> existing = new HashSet<>(partialList);
|
||||
long start = System.nanoTime();
|
||||
int found = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (!existing.contains(i)) found++; // O(1) per call
|
||||
}
|
||||
return System.nanoTime() - start;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
int minRatio = 5;
|
||||
|
||||
// [N = numPartitions, L = partialList.size() at expand time]
|
||||
int[][] cases = {
|
||||
{500, 250},
|
||||
{2000, 1000},
|
||||
{5000, 2500},
|
||||
};
|
||||
|
||||
// warmup
|
||||
for (int w = 0; w < 3; w++) {
|
||||
benchSlow(200, 100);
|
||||
benchFast(200, 100);
|
||||
}
|
||||
|
||||
for (int[] c : cases) {
|
||||
int N = c[0];
|
||||
int L = c[1];
|
||||
|
||||
long slowTotal = 0, fastTotal = 0;
|
||||
int reps = 10;
|
||||
for (int r = 0; r < reps; r++) {
|
||||
slowTotal += benchSlow(N, L);
|
||||
fastTotal += benchFast(N, L);
|
||||
}
|
||||
long slowAvg = slowTotal / reps;
|
||||
long fastAvg = fastTotal / reps;
|
||||
|
||||
double ratio = fastAvg > 0 ? (double) slowAvg / fastAvg : 999.0;
|
||||
boolean ok = ratio >= minRatio;
|
||||
System.out.printf(" N=%-5d L=%-5d slow=%8dns fast=%7dns ratio=%.1fx %s%n",
|
||||
N, L, slowAvg, fastAvg, ratio, ok ? "PASS" : "FAIL");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
System.out.printf("%nTotal: %d/%d PASS%n", passed, passed + failed);
|
||||
if (failed > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue