New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory growth in Channel usage #2803
Comments
I ran ktrace on this code on OpenBSD and there are a lot of
This leak also happens with For the record, you can get more accurate memory usage results using the use Telemetry;
my Channel $channel .= new;
my atomicint $count = 0;
react {
whenever $channel {
$channel.send: $_ + 1;
say T<max-rss> / 1024 ~ 'MB max-rss' if ++⚛$count %% 5000;
}
LEAVE $channel.send: 0;
} |
Starting to investigate this. This construct does not leak:
Which means it isn't something to do with the underlying blocking queue. By contrast, this does leak:
Meaning the |
Maybe this code doesn't leak because it's not doing anything? I don't see any output of it, and a run with Telemetry Report of Process #73156 (2019-04-05T13:36:04Z)
|
@lizmat Only if you forget to include the initial send, I think? :) Looking further into it: the queue in |
Ah, I shoulda spotted this much sooner. Here's how
It correctly avoids the potential race data loss bug, as the comments note, however that leads to a leak in the situation in this bug report. Each time around the loop we end up with something being added to the channel, and never relinquish control. However, we also get an async notification for each item that is set, having subscribed to them. Those notifications can't be handled right away since the So the ingredients are |
If the code that `tap`s the Supply then does a `send` on the Channel, then that will happen synchronously with the loop pulling from the Channel. The result is that the loop never ends. However, to avoid races in other situations, we subscribe to the async notifications of new items in the Channel before starting that loop. Since we cannot process any `whenever` events until setup logic is complete, this will cause those events to queue up, causing memory growth. This helps with #2803.
We need it for backtraces and context introspection. Otherwise, it can go. Preserving it can cause leaks involving taken closures: the taking of the closure has an ->outer frame that in turn points to a ->caller and keeps it alive. This was involved in the leak that was reported in rakudo/rakudo#2803.
With the two fixes above, and having run it for around 5 minutes to observe the memory behavior, it seems that it now reaches a plateau and stays there. So, hopefully resolved. |
Please include in tests |
The Problem
This is related to my SO question https://stackoverflow.com/questions/55352666/huge-memory-usage-with-circular-pipeline, regarding rapidly growing memory usage for a circular pipleline.
My 'circular' pipeline/queue reacts to a message from a
Channel
and places a new message onto the sameChannel
. The process is boostrapped by sending a single message onto theChannel
before the react block.The problem is memory usage is not stable and continues to grow quickly.
Expected Behavior
There is only ever one message in the
Channel
at any one time. As such buffer of messages should not grow, and the memory usage of the program should be stable.Actual Behavior
Memory grows quickly and does not stabilise. Lots of allocations and garbage collection activity.
Steps to Reproduce
Environment
perl6 -v
): Rakudo version 2019.03 built on MoarVM version 2019.03The text was updated successfully, but these errors were encountered: