java-topology/defects/doris/unit/BindExprGroupingAlgorithm.java

181 lines
7.7 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.*;
import java.util.stream.*;
/**
* Standalone unit test for doris-0001:
* BindExpression.processNonStandardAggregate — List.contains() per projection → O(P×G).
*
* Simulates processNonStandardAggregate():
* for each projection, check if it's in groupingExprs (passed as List).
*
* Compile: javac -d . BindExprGroupingAlgorithm.java
* Run: java unit.BindExprGroupingAlgorithm
*/
public class BindExprGroupingAlgorithm {
// ── Expression stubs ─────────────────────────────────────────────────────
static class Expression {
final String id;
Expression(String id) { this.id = id; }
@Override public boolean equals(Object o) {
return o instanceof Expression && id.equals(((Expression) o).id);
}
@Override public int hashCode() { return id.hashCode(); }
@Override public String toString() { return id; }
}
static class SlotReference extends Expression {
SlotReference(String id) { super(id); }
}
// ── Result ───────────────────────────────────────────────────────────────
static class Result {
final List<String> output; // projection labels: "alias:X" or "keep:X"
final long ns;
Result(List<String> output, long ns) { this.output = output; this.ns = ns; }
}
// ── Defective: Collection<Expression> as List → O(G) .contains per proj ─
static class DefectiveAlgorithm {
Result processNonStandardAggregate(
List<Expression> originalProjections,
Collection<Expression> groupingExprs) { // List passed → O(G) .contains
long t0 = System.nanoTime();
List<String> out = new ArrayList<>();
for (Expression projection : originalProjections) {
if (projection instanceof SlotReference
&& !groupingExprs.contains(projection)) { // CWE-407 site
out.add("alias:" + projection.id);
} else {
out.add("keep:" + projection.id);
}
}
return new Result(out, System.nanoTime() - t0);
}
}
// ── Fixed: convert to Set once → O(1) .contains ──────────────────────────
static class FixedAlgorithm {
Result processNonStandardAggregate(
List<Expression> originalProjections,
Collection<Expression> groupingExprs) {
long t0 = System.nanoTime();
// Ensure O(1) membership
Set<Expression> groupingSet = (groupingExprs instanceof Set)
? (Set<Expression>) groupingExprs
: new HashSet<>(groupingExprs); // O(G) once
List<String> out = new ArrayList<>();
for (Expression projection : originalProjections) {
if (projection instanceof SlotReference
&& !groupingSet.contains(projection)) { // O(1)
out.add("alias:" + projection.id);
} else {
out.add("keep:" + projection.id);
}
}
return new Result(out, System.nanoTime() - t0);
}
}
// ── Helpers ──────────────────────────────────────────────────────────────
static List<Expression> makeProjections(int P, int G) {
// First G projections are SlotReferences that ARE in groupingExprs → "keep"
// Next (P-G) are SlotReferences NOT in groupingExprs → "alias"
List<Expression> list = new ArrayList<>(P);
for (int i = 0; i < P; i++) {
list.add(new SlotReference("s" + i));
}
return list;
}
static List<Expression> makeGroupingList(int G) {
List<Expression> list = new ArrayList<>(G);
for (int i = 0; i < G; i++) list.add(new SlotReference("s" + i));
return list;
}
// ── Assertions ───────────────────────────────────────────────────────────
static void assertEquals(Object expected, Object actual, String msg) {
if (!expected.equals(actual))
throw new AssertionError(msg + ": expected=" + expected + " actual=" + actual);
}
static void assertTrue(boolean cond, String msg) {
if (!cond) throw new AssertionError(msg);
}
public static void main(String[] args) {
System.out.println("=== doris-0001: BindExprGroupingAlgorithm ===");
DefectiveAlgorithm defAlg = new DefectiveAlgorithm();
FixedAlgorithm fixAlg = new FixedAlgorithm();
// Correctness: small case
{
int P = 10, G = 4;
List<Expression> projections = makeProjections(P, G);
List<Expression> grouping = makeGroupingList(G);
Result dr = defAlg.processNonStandardAggregate(projections, grouping);
Result fr = fixAlg.processNonStandardAggregate(projections, grouping);
assertEquals(dr.output, fr.output, "output labels");
// First G should be "keep:", rest "alias:"
for (int i = 0; i < G; i++) assertTrue(dr.output.get(i).startsWith("keep:"), "keep at " + i);
for (int i = G; i < P; i++) assertTrue(dr.output.get(i).startsWith("alias:"), "alias at " + i);
System.out.println("PASS correctness (P=10, G=4)");
}
// Correctness: Set passed directly (should not double-wrap)
{
int P = 8, G = 3;
List<Expression> projections = makeProjections(P, G);
Set<Expression> groupingSet = new HashSet<>(makeGroupingList(G));
Result dr = defAlg.processNonStandardAggregate(projections, new ArrayList<>(groupingSet));
Result fr = fixAlg.processNonStandardAggregate(projections, groupingSet);
assertEquals(dr.output, fr.output, "Set input output labels");
System.out.println("PASS correctness Set input (P=8, G=3)");
}
// Benchmark at P=400, G=200
{
int P = 400, G = 200;
List<Expression> projections = makeProjections(P, G);
List<Expression> grouping = makeGroupingList(G);
// warm up
for (int i = 0; i < 5; i++) {
defAlg.processNonStandardAggregate(projections, new ArrayList<>(grouping));
fixAlg.processNonStandardAggregate(projections, new ArrayList<>(grouping));
}
long defNs = 0, fixNs = 0;
int reps = 50;
for (int i = 0; i < reps; i++) {
defNs += defAlg.processNonStandardAggregate(projections, new ArrayList<>(grouping)).ns;
fixNs += fixAlg.processNonStandardAggregate(projections, new ArrayList<>(grouping)).ns;
}
defNs /= reps; fixNs /= reps;
double ratio = (double) defNs / Math.max(1, fixNs);
System.out.printf("BENCH P=%d G=%d reps=%d%n", P, G, reps);
System.out.printf(" defective avg: %,d ns%n", defNs);
System.out.printf(" fixed avg: %,d ns%n", fixNs);
System.out.printf(" speedup: %.1fx%n", ratio);
assertTrue(ratio >= 2.0, "Expected fixed >= 2x faster, got " + ratio + "x");
System.out.println("PASS speedup >= 2x");
}
System.out.println("=== ALL PASS ===");
}
}