|
65 | 65 | * - Intelligent output streaming based on response size and complexity |
66 | 66 | * - Memory management with buffer optimization for large responses |
67 | 67 | * - Performance metrics collection for response generation analysis |
68 | | - * - Field-specific output optimizations for RAPI-style data patterns |
| 68 | + * - Field-specific output optimizations for JSON-style data patterns |
69 | 69 | * - Flow control patterns during response generation (from HTTP2FlowController concepts) |
70 | 70 | * - Streaming configuration based on payload characteristics |
71 | 71 | * |
|
77 | 77 | * - 30-50% performance improvement for large JSON responses (>1MB) |
78 | 78 | * - Reduced memory usage through intelligent buffering and streaming |
79 | 79 | * - Better throughput for concurrent JSON response generation |
80 | | - * - Specialized optimization for RAPI-style response patterns |
| 80 | + * - Specialized optimization for JSON-style response patterns |
81 | 81 | * - Prevents blocking behavior during large response generation |
82 | 82 | */ |
83 | 83 | public class EnhancedMoshiJsonFormatter implements MessageFormatter { |
@@ -148,7 +148,7 @@ public void writeTo(MessageContext outMsgCtxt, OMOutputFormat omOutputFormat, Ou |
148 | 148 | if (log.isDebugEnabled()) { |
149 | 149 | log.debug("EnhancedMoshiH2Formatter: [" + responseId + "] Large response detected - suggesting GC optimization"); |
150 | 150 | } |
151 | | - suggestGarbageCollectionForResponse(); |
| 151 | + monitorMemoryPressureForResponse(); |
152 | 152 | } |
153 | 153 |
|
154 | 154 | // Generate response with appropriate strategy |
@@ -245,7 +245,7 @@ private void generateLargeResponseOptimized(MessageContext outMsgCtxt, OMOutputF |
245 | 245 | // Apply memory optimization patterns (from HTTP/2 integration) |
246 | 246 | if (strategy.getEstimatedSize() > MEMORY_OPTIMIZATION_THRESHOLD) { |
247 | 247 | log.debug("Applying memory optimization for very large response: " + responseId); |
248 | | - suggestGarbageCollectionForResponse(); |
| 248 | + monitorMemoryPressureForResponse(); |
249 | 249 | } |
250 | 250 |
|
251 | 251 | generateWithEnhancedMoshi(outMsgCtxt, omOutputFormat, outputStream, preserve, strategy, responseId); |
@@ -429,7 +429,7 @@ private void generateCollectionResponseOptimized(java.util.Collection<?> collect |
429 | 429 |
|
430 | 430 | if (itemCount % 5000 == 0) { |
431 | 431 | // Memory management for very large collections |
432 | | - suggestGarbageCollectionForResponse(); |
| 432 | + monitorMemoryPressureForResponse(); |
433 | 433 |
|
434 | 434 | if (log.isDebugEnabled()) { |
435 | 435 | log.debug("Processed " + itemCount + " collection items for response: " + responseId); |
@@ -520,13 +520,26 @@ private String generateResponseId() { |
520 | 520 | } |
521 | 521 |
|
522 | 522 | /** |
523 | | - * Memory management for large responses (pattern from HTTP/2 integration). |
| 523 | + * Memory pressure monitoring for large responses. |
| 524 | + * Note: Removed System.gc() call - libraries should not interfere with application GC strategy. |
524 | 525 | */ |
525 | | - private void suggestGarbageCollectionForResponse() { |
| 526 | + private void monitorMemoryPressureForResponse() { |
526 | 527 | if (log.isDebugEnabled()) { |
527 | | - log.debug("Suggesting garbage collection for Enhanced Moshi H2 large response generation"); |
| 528 | + Runtime runtime = Runtime.getRuntime(); |
| 529 | + long totalMemory = runtime.totalMemory(); |
| 530 | + long freeMemory = runtime.freeMemory(); |
| 531 | + long usedMemory = totalMemory - freeMemory; |
| 532 | + double memoryUsage = (double) usedMemory / totalMemory * 100; |
| 533 | + |
| 534 | + log.debug("Memory pressure monitoring during large response generation: " |
| 535 | + + String.format("%.1f%% used (%s / %s)", memoryUsage, |
| 536 | + formatBytes(usedMemory), formatBytes(totalMemory))); |
| 537 | + |
| 538 | + if (memoryUsage > 85.0) { |
| 539 | + log.warn("High memory pressure detected (" + String.format("%.1f", memoryUsage) + "% used) during JSON response generation. " + |
| 540 | + "Consider increasing heap size or reducing response size."); |
| 541 | + } |
528 | 542 | } |
529 | | - System.gc(); |
530 | 543 | } |
531 | 544 |
|
532 | 545 | /** |
@@ -682,7 +695,7 @@ public void writeStartElement(String localName) throws XMLStreamException { |
682 | 695 |
|
683 | 696 | // Apply memory optimization for large responses |
684 | 697 | if (strategy.isLargeResponse() && shouldOptimizeMemory()) { |
685 | | - optimizeMemoryForLargeResponse(); |
| 698 | + monitorMemoryForLargeResponse(); |
686 | 699 | } |
687 | 700 |
|
688 | 701 | // Call parent implementation |
@@ -714,7 +727,7 @@ public void writeCharacters(String text) throws XMLStreamException { |
714 | 727 |
|
715 | 728 | // Memory pressure monitoring for very large text content |
716 | 729 | if (text.length() > 10000 && shouldOptimizeMemory()) { |
717 | | - optimizeMemoryForLargeResponse(); |
| 730 | + monitorMemoryForLargeResponse(); |
718 | 731 | } |
719 | 732 | } |
720 | 733 |
|
@@ -794,20 +807,33 @@ private boolean shouldOptimizeMemory() { |
794 | 807 | } |
795 | 808 |
|
796 | 809 | /** |
797 | | - * Apply memory optimization for large responses. |
| 810 | + * Monitor memory pressure during large response processing. |
| 811 | + * Note: Removed System.gc() call - libraries should not interfere with application GC strategy. |
798 | 812 | */ |
799 | | - private void optimizeMemoryForLargeResponse() { |
| 813 | + private void monitorMemoryForLargeResponse() { |
800 | 814 | long currentTime = System.nanoTime(); |
801 | 815 |
|
802 | | - // Avoid too frequent GC hints (max once per 5 seconds) |
| 816 | + // Avoid too frequent memory checks (max once per 5 seconds) |
803 | 817 | if (currentTime - lastGcHint > 5_000_000_000L) { |
| 818 | + Runtime runtime = Runtime.getRuntime(); |
| 819 | + long totalMemory = runtime.totalMemory(); |
| 820 | + long freeMemory = runtime.freeMemory(); |
| 821 | + long usedMemory = totalMemory - freeMemory; |
| 822 | + double memoryUsage = (double) usedMemory / totalMemory * 100; |
| 823 | + |
804 | 824 | if (enhancedLog.isDebugEnabled()) { |
805 | | - enhancedLog.debug("EnhancedMoshiXMLStreamWriter: [" + responseId + "] Suggesting GC for memory optimization"); |
| 825 | + enhancedLog.debug("EnhancedMoshiXMLStreamWriter: [" + responseId + "] Memory monitoring: " |
| 826 | + + String.format("%.1f%% used (%s / %s)", memoryUsage, |
| 827 | + formatBytesLocal(usedMemory), formatBytesLocal(totalMemory))); |
| 828 | + } |
| 829 | + |
| 830 | + if (memoryUsage > 85.0) { |
| 831 | + enhancedLog.warn("High memory pressure detected (" + String.format("%.1f", memoryUsage) + "% used) in XML stream writer. " + |
| 832 | + "Consider increasing heap size."); |
806 | 833 | } |
807 | 834 |
|
808 | | - System.gc(); // Hint for garbage collection |
809 | 835 | lastGcHint = currentTime; |
810 | | - memoryOptimized = true; |
| 836 | + memoryOptimized = true; // Keep this flag to indicate memory monitoring occurred |
811 | 837 | } |
812 | 838 | } |
813 | 839 |
|
|
0 commit comments