Project

General

Profile

개선(improvement) #2626

Updated by Dante Le 3 months ago

**Parent Issue**: #2310 [BE] Optimize Memory, CPU API search list flight 

 ## Summary 

 Triple nested loop structure in `getForFilter()` method causing O(n³) complexity, with inner linear searches escalating to O(n⁴) performance. 

 ## Location 

 **File**: `web-api/src/main/java/com/ohmy/api/service/flight/FlightListItineraryService.java` 
 **Method**: `getForFilter()` 
 **Lines**: 134-618 (485 lines) 

 ## Problem Code Pattern 

 ```java 
 <pre><code class="java"> 
 // Lines 169-600: Triple nested loop structure 
 for (JsonNode fareJsonNode : responseJsonNode.at("/result/combinedFares")) {           // Loop 1: fares 
     for (int itineraryIndex = 0; itineraryIndex < itineraryIndexes.size(); ...) {      // Loop 2: itineraries 
         for (JsonNode segmentJsonNode : ...) {                                          // Loop 3: segments 
             // Lines 290-294: Linear search INSIDE triple loop 
             ObjectNode cabinClassJsonNode = StreamSupport.stream(cabinClassArrayNode.spliterator(), false) 
                     .filter(x -> x.get("code").textValue().equals(cabinClassCode)) 
                     .findFirst() 
                     .map(x -> (ObjectNode) x) 
                     .orElse(null); 
         } 
     } 
 } 
 </code></pre> ``` 

 ## Performance Impact 

 **Computational Complexity**: 
 - Base iterations: 500 fares × 3 itineraries × 10 segments = **15,000 iterations** 
 - With inner linear searches: O(n⁴) = **45M+ operations** in worst case 
 - Causes significant CPU spikes under concurrent load 

 **Real-world Impact**: 
 - Contributes to memory exhaustion under ~50 concurrent requests 
 - Part of the 1.5 GB peak memory allocation issue 
 - Slows response time proportionally to result set size 

 ## Required Fix 

 ### 1. Pre-compute Lookup Maps 
 Replace linear searches with O(1) HashMap lookups: 
 - Cabin classes map: `Map<String, ObjectNode> cabinClassByCode` 
 - Airlines map: `Map<String, JsonNode> airlineByCode` 
 - Alliances map: `Map<String, JsonNode> allianceByCode` 

 ### 2. Extract to Smaller Methods 
 Break down 485-line method into focused functions: 
 - `buildFilterContext()` - Pre-build all lookup maps 
 - `filterFaresByItinerary()` - Single responsibility per iteration level 
 - `matchSegmentCriteria()` - Segment-level filtering logic 

 ### 3. Consider Caching 
 Cache filter results by fare signature if filters don't change between requests. 

 ## Acceptance Criteria 

 ✅ **MUST maintain 100% identical API response** (no logic changes) 
 ✅ Reduce computational complexity from O(n⁴) to O(n²) or better 
 ✅ Pre-build lookup maps once per request 
 ✅ Verify performance improvement with load testing 
 ✅ Measure CPU reduction under 50 concurrent requests 

 ## Constraints 

 ⚠️ **NO LOGIC CHANGES ALLOWED** - This is a performance optimization only 
 - Do not modify filter behavior or output format 
 - Do not alter calculation results 
 - API response must remain byte-for-byte identical 

 ## Related Issues 

 - #2610 - CRITICAL-1: Excessive JsonNode Traversal (Fixed ✅) 
 - #2611 - AtomicReference Memory Retention (Fixed ✅) 
 - Part of Phase 3: Major Refactoring in optimization roadmap 

 ## Reference 

 See `docs/flight-list-itinerary/VERIFIED_ISSUES.md` - CRITICAL-2 section for complete analysis.

Back

Add picture from clipboard (Maximum size: 50 MB)