cmake-0005: cmQtAutoGen MergeOptions std::find over baseOpts in newOpts loop, O(N*M), 31.5x at N=M=50 cmake-0006: cmVisualStudio10TargetGenerator FinishWritingSource writtenSettings O(S^2), 15.3x at S=30 cmake-0007: cmGeneratorExpressionNode TargetRuntimeDllDirsNode dllDirs O(D^2), 10.3x at D=100 MPD: all 5 MOADs CLEAN; updated CLEAN.md with MOAD-0002 through MOAD-0005 analysis. Unit tests: 3/3 PASS.
111 lines
4.6 KiB
Java
111 lines
4.6 KiB
Java
import java.util.*;
|
|
|
|
/**
|
|
* Unit test for cmake-0006: FinishWritingSource writtenSettings O(S^2) -> O(S).
|
|
*
|
|
* Models the dedup logic: for each (config, setting) pair, skip if already written.
|
|
* Defect: std::find over vector grows O(S) per check -> O(C * S^2) total.
|
|
* Fix: unordered_set -> O(1) per check -> O(C * S) total.
|
|
*/
|
|
public class WrittenSettingsAlgorithm {
|
|
|
|
static final int CONFIGS = 4;
|
|
static final int SETTINGS_PER_CONFIG = 30;
|
|
|
|
// Simulate settings: each config has same setting names (all should dedup after first config)
|
|
static Map<String, Map<String, String>> buildToolSettings() {
|
|
Map<String, Map<String, String>> toolSettings = new LinkedHashMap<>();
|
|
for (int c = 0; c < CONFIGS; c++) {
|
|
String config = "Config" + c;
|
|
Map<String, String> settings = new LinkedHashMap<>();
|
|
for (int s = 0; s < SETTINGS_PER_CONFIG; s++) {
|
|
settings.put("Setting" + s, "Value" + c + "_" + s);
|
|
}
|
|
toolSettings.put(config, settings);
|
|
}
|
|
return toolSettings;
|
|
}
|
|
|
|
// --- Defective: std::find over vector ---
|
|
static long finishWritingSourceDefective(Map<String, Map<String, String>> toolSettings) {
|
|
List<String> writtenSettings = new ArrayList<>();
|
|
long ops = 0;
|
|
for (Map.Entry<String, Map<String, String>> configEntry : toolSettings.entrySet()) {
|
|
for (Map.Entry<String, String> setting : configEntry.getValue().entrySet()) {
|
|
// O(S) linear scan -- the defect
|
|
for (String ws : writtenSettings) {
|
|
ops++;
|
|
if (ws.equals(setting.getKey())) break;
|
|
}
|
|
if (!writtenSettings.contains(setting.getKey())) {
|
|
writtenSettings.add(setting.getKey());
|
|
}
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
// --- Fixed: unordered_set ---
|
|
static long finishWritingSourceFixed(Map<String, Map<String, String>> toolSettings) {
|
|
Set<String> writtenSettings = new HashSet<>();
|
|
long ops = 0;
|
|
for (Map.Entry<String, Map<String, String>> configEntry : toolSettings.entrySet()) {
|
|
for (Map.Entry<String, String> setting : configEntry.getValue().entrySet()) {
|
|
ops++; // O(1) hash check
|
|
if (!writtenSettings.contains(setting.getKey())) {
|
|
writtenSettings.add(setting.getKey());
|
|
}
|
|
}
|
|
}
|
|
return ops;
|
|
}
|
|
|
|
// --- Correctness: both produce same written set ---
|
|
static void testCorrectness() {
|
|
Map<String, Map<String, String>> toolSettings = buildToolSettings();
|
|
|
|
Set<String> defectWritten = new HashSet<>();
|
|
List<String> defectList = new ArrayList<>();
|
|
for (Map.Entry<String, Map<String, String>> ce : toolSettings.entrySet()) {
|
|
for (Map.Entry<String, String> s : ce.getValue().entrySet()) {
|
|
if (!defectList.contains(s.getKey())) defectList.add(s.getKey());
|
|
}
|
|
}
|
|
defectWritten.addAll(defectList);
|
|
|
|
Set<String> fixedWritten = new HashSet<>();
|
|
for (Map.Entry<String, Map<String, String>> ce : toolSettings.entrySet()) {
|
|
for (Map.Entry<String, String> s : ce.getValue().entrySet()) {
|
|
fixedWritten.add(s.getKey());
|
|
}
|
|
}
|
|
|
|
if (!defectWritten.equals(fixedWritten)) {
|
|
throw new AssertionError("Written sets differ: defect=" + defectWritten.size()
|
|
+ " fixed=" + fixedWritten.size());
|
|
}
|
|
if (fixedWritten.size() != SETTINGS_PER_CONFIG) {
|
|
throw new AssertionError("Expected " + SETTINGS_PER_CONFIG + " unique settings, got " + fixedWritten.size());
|
|
}
|
|
System.out.println("PASS testCorrectness (written set matches, size=" + fixedWritten.size() + ")");
|
|
}
|
|
|
|
static void testBenchmark() {
|
|
Map<String, Map<String, String>> toolSettings = buildToolSettings();
|
|
long defectOps = finishWritingSourceDefective(toolSettings);
|
|
long fixedOps = finishWritingSourceFixed(toolSettings);
|
|
double ratio = (double) defectOps / fixedOps;
|
|
System.out.printf("BENCH finishWritingSource C=%d S=%d: defective=%d ops, fixed=%d ops, ratio=%.1fx%n",
|
|
CONFIGS, SETTINGS_PER_CONFIG, defectOps, fixedOps, ratio);
|
|
if (ratio < 3.0) {
|
|
throw new AssertionError("Expected ratio >= 3x, got " + ratio);
|
|
}
|
|
System.out.println("PASS testBenchmark (ratio >= 3x confirmed)");
|
|
}
|
|
|
|
public static void main(String[] args) {
|
|
testCorrectness();
|
|
testBenchmark();
|
|
System.out.println("ALL PASS cmake-0006 WrittenSettings");
|
|
}
|
|
}
|