개선(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.