@@ -26,21 +26,7 @@ public class QueryRewritingBenchmark extends OpenSearchTestCase {
2626 private static final int WARMUP_ITERATIONS = 1000 ;
2727 private static final int BENCHMARK_ITERATIONS = 10000 ;
2828
29- public void testQueryRewritingPerformanceAndValue () {
30- System .out .println ("\n ====== QUERY REWRITING BENCHMARK ======\n " );
31-
32- // Benchmark different query patterns
33- benchmarkFilterMerging ();
34- benchmarkNestedFlattening ();
35- benchmarkComplexRealWorldQuery ();
36-
37- System .out .println ("\n ======================================" );
38- }
39-
40- private void benchmarkFilterMerging () {
41- System .out .println ("1. FILTER MERGING OPTIMIZATION" );
42- System .out .println (" Scenario: Multiple term queries on same field\n " );
43-
29+ public void testFilterMergingPerformance () {
4430 // Create query with multiple terms that can be merged
4531 BoolQueryBuilder query = QueryBuilders .boolQuery ();
4632 String [] brands = { "apple" , "samsung" , "dell" , "hp" , "lenovo" , "asus" , "acer" , "msi" };
@@ -49,35 +35,28 @@ private void benchmarkFilterMerging() {
4935 }
5036
5137 BenchmarkResult result = runBenchmark ("Filter Merging" , query );
52- result .print ();
5338
54- // Show the optimization
55- System . out . println ( " Original: 8 separate term queries → 8 field lookups" );
56- System . out . println ( " Optimized: 1 terms query → 1 field lookup" );
57- System . out . println ( " Expected execution speedup: 3-5x for filter evaluation \n " );
39+ // Assert significant node reduction
40+ assertTrue ( "Should reduce nodes by > 70%" , result . getReductionPercent () > 70 );
41+ assertTrue ( "Rewrite overhead should be < 50 microseconds" , result . rewriteOverhead < 50 );
42+ assertTrue ( "ROI should be positive" , result . getROI () > 1 );
5843 }
5944
60- private void benchmarkNestedFlattening () {
61- System .out .println ("2. NESTED BOOLEAN FLATTENING" );
62- System .out .println (" Scenario: Deeply nested boolean queries\n " );
63-
45+ public void testNestedFlatteningPerformance () {
6446 // Create deeply nested query
6547 QueryBuilder innerQuery = QueryBuilders .termQuery ("status" , "active" );
6648 for (int i = 0 ; i < 5 ; i ++) {
6749 innerQuery = QueryBuilders .boolQuery ().must (QueryBuilders .matchAllQuery ()).filter (innerQuery );
6850 }
6951
7052 BenchmarkResult result = runBenchmark ("Nested Flattening" , innerQuery );
71- result .print ();
7253
73- System .out .println (" Optimization: Removed 5 levels of nesting + 5 match_all queries" );
74- System .out .println (" Benefit: Reduced call stack depth, less memory allocation\n " );
54+ // Assert optimization effectiveness
55+ assertTrue ("Should reduce nodes by > 80%" , result .getReductionPercent () > 80 );
56+ assertTrue ("Rewrite overhead should be < 100 microseconds" , result .rewriteOverhead < 100 );
7557 }
7658
77- private void benchmarkComplexRealWorldQuery () {
78- System .out .println ("3. REAL-WORLD E-COMMERCE QUERY" );
79- System .out .println (" Scenario: Complex faceted search with multiple filters\n " );
80-
59+ public void testComplexRealWorldQueryPerformance () {
8160 QueryBuilder query = QueryBuilders .boolQuery ()
8261 // Category filters
8362 .filter (
@@ -105,27 +84,28 @@ private void benchmarkComplexRealWorldQuery() {
10584 .filter (QueryBuilders .matchAllQuery ());
10685
10786 BenchmarkResult result = runBenchmark ("E-commerce Query" , query );
108- result .print ();
109-
110- System .out .println (" Optimizations applied:" );
111- System .out .println (" - Merged 3 category terms → 1 terms query" );
112- System .out .println (" - Merged 5 brand terms → 1 terms query" );
113- System .out .println (" - Removed 2 match_all queries" );
114- System .out .println (" - Flattened nested structure" );
115- System .out .println (" Real impact: 50%+ faster query execution for this pattern\n " );
87+
88+ // Assert real-world optimization value
89+ assertTrue ("Should reduce nodes by > 50%" , result .getReductionPercent () > 50 );
90+ assertTrue ("Rewrite overhead should be reasonable" , result .rewriteOverhead < 200 );
91+ assertTrue ("Should provide significant ROI" , result .getROI () > 10 );
11692 }
11793
11894 private BenchmarkResult runBenchmark (String name , QueryBuilder query ) {
95+ // Warmup
11996 for (int i = 0 ; i < WARMUP_ITERATIONS ; i ++) {
12097 QueryRewriterRegistry .rewrite (query , context , true );
12198 QueryRewriterRegistry .rewrite (query , context , false );
12299 }
100+
101+ // Benchmark without rewriting
123102 long startWithout = System .nanoTime ();
124103 for (int i = 0 ; i < BENCHMARK_ITERATIONS ; i ++) {
125104 QueryRewriterRegistry .rewrite (query , context , false );
126105 }
127106 long timeWithout = System .nanoTime () - startWithout ;
128107
108+ // Benchmark with rewriting
129109 long startWith = System .nanoTime ();
130110 QueryBuilder optimized = null ;
131111 for (int i = 0 ; i < BENCHMARK_ITERATIONS ; i ++) {
@@ -184,19 +164,15 @@ private static class BenchmarkResult {
184164 this .totalTimeWithout = totalTimeWithout ;
185165 }
186166
187- void print () {
188- double reduction = (nodesBefore - nodesAfter ) * 100.0 / nodesBefore ;
189- double overhead = (totalTimeWith - totalTimeWithout ) * 100.0 / totalTimeWithout ;
190-
191- System .out .printf (" Query nodes: %d → %d (%.1f%% reduction)\n " , nodesBefore , nodesAfter , reduction );
192- System .out .printf (" Rewrite overhead: %.2f μs (%.1f%% of baseline)\n " , rewriteOverhead , overhead );
193-
194- // Value calculation: assume each node reduction saves 0.5-1ms in execution
195- double estimatedSavings = (nodesBefore - nodesAfter ) * 0.75 ; // ms
196- double breakEven = rewriteOverhead / 1000.0 ; // convert to ms
167+ double getReductionPercent () {
168+ return (nodesBefore - nodesAfter ) * 100.0 / nodesBefore ;
169+ }
197170
198- System .out .printf (" Value: Saves ~%.1f ms execution time for %.3f ms rewrite cost\n " , estimatedSavings , breakEven );
199- System .out .printf (" ROI: %.0fx return (rewrite once, execute many times)\n " , estimatedSavings / breakEven );
171+ double getROI () {
172+ // Assume each node reduction saves 0.5-1ms in execution
173+ double estimatedSavingsMs = (nodesBefore - nodesAfter ) * 0.75 ;
174+ double rewriteCostMs = rewriteOverhead / 1000.0 ;
175+ return estimatedSavingsMs / rewriteCostMs ;
200176 }
201177 }
202178}
0 commit comments