java-topology/defects/lldb/unit/LldbSerializedBpNamesAlgorithm.java

138 lines
5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package unit;
import java.util.*;
/**
* Unit test for lldb-0001: SerializedBreakpointMatchesNames O(B×N²) vector scan.
*
* Models the defect: for each breakpoint in a serialized session file, check each
* of the breakpoint's names against a filter list using linear vector scan.
* Fix: convert the filter list to a HashSet before the loop.
*/
public class LldbSerializedBpNamesAlgorithm {
// --- SLOW: llvm::is_contained on vector (models Breakpoint.cpp:247) ---
static class SlowResult {
long ops;
int matched;
SlowResult(long ops, int matched) { this.ops = ops; this.matched = matched; }
}
/**
* O(B * N_bp * F): for each breakpoint, for each name on the breakpoint,
* linearly scan the filter list.
*
* @param bpNames list of breakpoints; each element is the list of names on that bp
* @param filter filter list as ArrayList (models std::vector<std::string>)
*/
static SlowResult slowMatchesNames(List<List<String>> bpNames, List<String> filter) {
long ops = 0;
int matched = 0;
for (List<String> bpNameList : bpNames) { // O(B)
boolean found = false;
for (String name : bpNameList) { // O(N_bp)
for (String f : filter) { // O(F) - llvm::is_contained
ops++;
if (f.equals(name)) {
found = true;
break;
}
}
if (found) break;
}
if (found) matched++;
}
return new SlowResult(ops, matched);
}
// --- FAST: convert filter to HashSet once, then O(1) lookup ---
static class FastResult {
long ops;
int matched;
FastResult(long ops, int matched) { this.ops = ops; this.matched = matched; }
}
/**
* O(B * N_bp): convert filter to HashSet once, then O(1) per name check.
*/
static FastResult fastMatchesNames(List<List<String>> bpNames, List<String> filter) {
Set<String> filterSet = new HashSet<>(filter); // O(F) once
long ops = 0;
int matched = 0;
for (List<String> bpNameList : bpNames) { // O(B)
boolean found = false;
for (String name : bpNameList) { // O(N_bp)
ops++;
if (filterSet.contains(name)) { // O(1)
found = true;
break;
}
}
if (found) matched++;
}
return new FastResult(ops, matched);
}
// --- Test cases ---
static boolean runTest(String label, int B, int N_bp, int F, double minRatio) {
// Build filter list: F names like "bp-filter-NNN"
List<String> filter = new ArrayList<>();
for (int i = 0; i < F; i++) {
filter.add("bp-filter-" + i);
}
// Build breakpoint name lists: each bp has N_bp names
// Every other bp matches (its first name is in the filter)
List<List<String>> bpNames = new ArrayList<>();
for (int b = 0; b < B; b++) {
List<String> names = new ArrayList<>();
for (int n = 0; n < N_bp; n++) {
if (b % 2 == 0 && n == N_bp - 1) {
// match: last name in list is a filter entry (worst case - full scan)
names.add("bp-filter-" + (b % F));
} else {
names.add("bp-name-" + b + "-" + n);
}
}
bpNames.add(names);
}
SlowResult slow = slowMatchesNames(bpNames, filter);
FastResult fast = fastMatchesNames(bpNames, filter);
// Verify correctness
if (slow.matched != fast.matched) {
System.out.printf(" FAIL %s: match count mismatch slow=%d fast=%d%n",
label, slow.matched, fast.matched);
return false;
}
double ratio = (double) slow.ops / fast.ops;
boolean pass = ratio >= minRatio;
System.out.printf(" %s %s: B=%d N_bp=%d F=%d | SLOW=%d ops FAST=%d ops ratio=%.1fx%n",
pass ? "PASS" : "FAIL", label, B, N_bp, F, slow.ops, fast.ops, ratio);
return pass;
}
public static void main(String[] args) {
int pass = 0, total = 0;
// Test 1: B=100 breakpoints, N_bp=10 names each, F=20 filter names
total++; if (runTest("B=100,Nbp=10,F=20", 100, 10, 20, 5.0)) pass++;
// Test 2: B=200, N_bp=15, F=50 - more filter entries amplifies ratio
total++; if (runTest("B=200,Nbp=15,F=50", 200, 15, 50, 10.0)) pass++;
// Test 3: B=500, N_bp=20, F=100 - representative large session restore
total++; if (runTest("B=500,Nbp=20,F=100", 500, 20, 100, 20.0)) pass++;
// Test 4: B=50, N_bp=5, F=10 - small case, ratio still >= 5x
total++; if (runTest("B=50,Nbp=5,F=10", 50, 5, 10, 5.0)) pass++;
System.out.printf("%n%d/%d PASS%n", pass, total);
if (pass < total) System.exit(1);
}
}