Skip to content
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

Use WeakRefs for spawned tasks to avoid holding unexpected references #1058

Merged
merged 8 commits into from
Dec 8, 2022

Conversation

quinnj
Copy link
Member

@quinnj quinnj commented Dec 7, 2022

Most complete explanation is here.

Also discussed here.

This PR proposes an alternative solution to clear_thread_states where that approach can be problematic (interferring with global thread state, not working as expected in nested spawned tasks, etc.). The previous definition also started unending Timer tasks that could build up over time.

The approach in this PR is to wrap spawned task closure arguments in WeakRef to allow them to be GCed as expected once the tasks are finished.

Most complete explanation is [here](JuliaLang/julia#40626 (comment)).

Also discussed [here](#1057).

This PR proposes an alternative solution to `clear_thread_states` where that approach
can be problematic (interferring with global thread state, not working as expected in nested spawned
tasks, etc.). The previous definition also started unending `Timer` tasks that could build up over time.

The approach in this PR is to wrap spawned task closure arguments in `WeakRef` to allow them to be
GCed as expected once the tasks are finished.
@codecov
Copy link

codecov bot commented Dec 7, 2022

Codecov Report

Base: 89.91% // Head: 89.78% // Decreases project coverage by -0.12% ⚠️

Coverage data is based on head (a235c99) compared to base (35e8402).
Patch coverage: 100.00% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1058      +/-   ##
==========================================
- Coverage   89.91%   89.78%   -0.13%     
==========================================
  Files           8        8              
  Lines        2250     2241       -9     
==========================================
- Hits         2023     2012      -11     
- Misses        227      229       +2     
Impacted Files Coverage Δ
src/CSV.jl 66.66% <ø> (ø)
src/context.jl 88.47% <ø> (-0.32%) ⬇️
src/utils.jl 85.20% <ø> (+0.25%) ⬆️
src/file.jl 94.60% <100.00%> (-0.02%) ⬇️
src/detection.jl 95.00% <0.00%> (-0.72%) ⬇️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

src/utils.jl Outdated
but with an `_` prefix; this avoids the original input being capture by `Task` closure. So usage is like:

```julia
@weakrefspawn ctx foo begin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add the @sync part around it to give a full example of intended use?

src/utils.jl Outdated
end

A macro that wraps a `Threads.@spawn` block with `WeakRef` calls for all `args...` arguments, allowing
them to be garbage collected once the `Task` has finished running. Must be used within a `@syncpreserve`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this!

Above @sync not @syncpreserve is used. Which is correct?

Also are we sure that the "preserve" part touches only the selected variables (this is relevant, as inside the task GC might have to be run if the taks itself allocates a lot).

@quinnj
Copy link
Member Author

quinnj commented Dec 7, 2022

@bkamins, I've updated this PR to use the @wkspawn macro now provided in the WorkerUtilities.jl package: JuliaServices/ConcurrentUtilities.jl#10. I moved it there because I have a few other multithreaded/concurrency-related utilities there and I want to use this in the Arrow.jl package as well.

As noted in that PR, the @wkspawn macro is a drop-in replacement for Threads.@spawn, but will pass mutable closure arguments wrapped in WeakRef to the spawn block expression.

@quinnj quinnj merged commit 077e177 into main Dec 8, 2022
@quinnj quinnj deleted the jq-weakref-spawn branch December 8, 2022 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants