Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions base/gcutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,19 @@ macro preserve(args...)
end)
end

"""
GC.safepoint()

Inserts a point in the program where garbage collection may run.
This can be useful in rare cases in multi-threaded programs where some threads
are allocating memory (and hence may need to run GC) but other threads are doing
only simple operations (no allocation, task switches, or I/O).
Copy link
Member

Choose a reason for hiding this comment

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

Ok, but where would you put this call?

Copy link
Member

Choose a reason for hiding this comment

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

An example would be pretty helpful here.

Copy link
Member

@mbauman mbauman Aug 27, 2019

Choose a reason for hiding this comment

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

Naive question, and maybe this isn't the place to put this information, but why does the compute thread need to have a safepoint if it's not allocating any objects? If the other threads are allocating then they're hitting safepoints... so if the GC determines it needs to collect on one thread does it block and wait for all other threads to similarly block at safepoints before collecting?

Edit: so would that mean you'd want to structure it in the compute loop to run every N milliseconds, where N is near your maximum acceptable GC latency of the other threads and/or on the same order as the average time-to-safepoint of the other threads?

Copy link
Member Author

Choose a reason for hiding this comment

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

if the GC determines it needs to collect on one thread does it block and wait for all other threads to similarly block at safepoints before collecting

Yes.

Running it every N milliseconds would be nice, but pretty fancy. If you can tolerate a bit of slowdown you can just throw it in a loop anywhere. It's only a single load instruction so it's not horribly expensive. I also wouldn't advise using it at all unless the computation takes a really long time.

Copy link
Member

Choose a reason for hiding this comment

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

Right — I wasn't imaging a timer, but rather giving the docs reader some sort of rule of thumb to allow them to do some reasoning about a rough number of inner loop iterations to run before hitting a safepoint. Of course, you also wouldn't want it in the lowest of loops as it'd break vectorizaton.

Calling this function periodically in non-allocating threads allows garbage
collection to run.

!!! compat "Julia 1.4"
This function is available as of Julia 1.4.
"""
safepoint() = ccall(:jl_gc_safepoint, Cvoid, ())

end # module GC
1 change: 1 addition & 0 deletions doc/src/base/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ Base.functionloc(::Method)
Base.GC.gc
Base.GC.enable
Base.GC.@preserve
Base.GC.safepoint
Meta.lower
Meta.@lower
Meta.parse(::AbstractString, ::Int)
Expand Down