Unlink dead nodes in MpscLinkedQueue · ReactiveX/RxJava@4c6c6fa (original) (raw)
Navigation Menu
- GitHub Copilot Write better code with AI
- GitHub Models New Manage and compare prompts
- GitHub Advanced Security Find and fix vulnerabilities
- Actions Automate any workflow
- Codespaces Instant dev environments
- Issues Plan and track work
- Code Review Manage code changes
- Discussions Collaborate outside of code
- Code Search Find more, search less
- Explore
- Pricing
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Appearance settings
Commit 4c6c6fa
Unlink dead nodes in MpscLinkedQueue
Similar tohttps://github.com/JCTools/JCTools/blob/master/jctools-core/src/main/java/org/jctools/queues/MpscLinkedQueue.java#L120, null out the next pointer in the discarded consumer node when polling from the queue. If not, we leave behind a (potentially long) chain of connected garbage nodes. If we're unlucky (for example one of the early nodes is promoted to old generation, triggering nepotism), this can cause GC issues as now we have a long linked list which must be marked by young collections. Reproducer: ``` import io.reactivex.rxjava3.internal.queue.MpscLinkedQueue; public class MpscLinkedQueueGC { public static void main(String[] args) { MpscLinkedQueue queue = new MpscLinkedQueue<>(); for (int i = 0; i < 10; i++) System.gc(); // tenure consumer node while (true) { queue.offer(123); queue.poll(); } } } ``` ``` Before fix: $ java -Xlog:gc -Xmx1G -cp build/classes/java/main MpscLinkedQueueGC.java ... [1.261s] GC(20) Pause Young (Normal) (G1 Preventive Collection) 115M->115M(204M) 209.335ms [1.385s] GC(23) Pause Young (Normal) (G1 Evacuation Pause) 148M->149M(204M) 31.491ms [1.417s] GC(24) Pause Young (Normal) (G1 Evacuation Pause) 157M->158M(204M) 19.333ms [1.453s] GC(25) Pause Young (Normal) (G1 Evacuation Pause) 166M->167M(599M) 22.678ms [1.966s] GC(26) Pause Young (Normal) (G1 Evacuation Pause) 249M->249M(497M) 305.238ms ... After fix: $ java -Xlog:gc -Xmx1G -cp build/classes/java/main MpscLinkedQueueGC.java ... [1.169s] GC(14) Pause Young (Normal) (G1 Evacuation Pause) 304M->2M(506M) 0.755ms [1.558s] GC(15) Pause Young (Normal) (G1 Evacuation Pause) 304M->2M(506M) 0.689ms [1.948s] GC(16) Pause Young (Normal) (G1 Evacuation Pause) 304M->2M(506M) 0.800ms [2.337s] GC(17) Pause Young (Normal) (G1 Evacuation Pause) 304M->2M(506M) 0.714ms ... ```
File tree
1 file changed
lines changed
- src/main/java/io/reactivex/rxjava3/internal/queue
1 file changed
lines changed
Lines changed: 2 additions & 0 deletions
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -99,6 +99,8 @@ public T poll() { | ||
99 | 99 | // we have to null out the value because we are going to hang on to the node |
100 | 100 | nextValue = nextNode.getAndNullValue(); |
101 | 101 | spConsumerNode(nextNode); |
102 | +// unlink previous consumer to help gc | |
103 | +currConsumerNode.soNext(null); | |
102 | 104 | return nextValue; |
103 | 105 | } |
104 | 106 |