Skip to content

Commit

Permalink
alloc profiler: adjust warnings in docs; remove logged warning from i…
Browse files Browse the repository at this point in the history
…mplementation (JuliaLang#44077)

* docs: update warning in the manual; add to reference

* remove missed allocs warning from `fetch`

since we think we've gotten all the allocs

* remove tests of warning message, since it's no longer there
  • Loading branch information
vilterp authored and LilithHafner committed Mar 8, 2022
1 parent 8215591 commit 81b64c2
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 68 deletions.
10 changes: 6 additions & 4 deletions doc/src/manual/profile.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,12 @@ Passing `sample_rate=1.0` will make it record everything (which is slow);
!!! note

The current implementation of the Allocations Profiler _does not
capture all allocations._ You can read more about the missing allocations
and the plan to improve this, here: https://github.com/JuliaLang/julia/issues/43688.
Calling `Profile.Allocs.fetch()` will print a log line reporting the percentage
of missed allocations, so you can understand the accuracy of your profile.
capture types for all allocations._ Allocations for which the profiler
could not capture the type are represented as having type
`Profile.Allocs.UnknownType`.

You can read more about the missing types and the plan to improve this, here:
https://github.com/JuliaLang/julia/issues/43688.

## External Profiling

Expand Down
48 changes: 9 additions & 39 deletions stdlib/Profile/src/Allocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ julia> results = Profile.Allocs.fetch()
julia> last(sort(results.allocs, by=x->x.size))
Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576)
```
Note: The current implementation of the Allocations Profiler _does not
capture types for all allocations._ Allocations for which the profiler
could not capture the type are represented as having type
`Profile.Allocs.UnknownType`.
You can read more about the missing types and the plan to improve this, here:
https://github.com/JuliaLang/julia/issues/43688.
"""
macro profile(opts, ex)
_prof_expr(ex, opts)
Expand All @@ -52,12 +60,6 @@ macro profile(ex)
_prof_expr(ex, :(sample_rate=0.0001))
end

# globals used for tracking how many allocs we're missing
# vs the alloc counters used by @time
const _g_gc_num_before = Ref{Base.GC_Num}()
const _g_sample_rate = Ref{Real}()
const _g_expected_sampled_allocs = Ref{Float64}(0)

function _prof_expr(expr, opts)
quote
$start(; $(esc(opts)))
Expand All @@ -77,9 +79,6 @@ A sample rate of 1.0 will record everything; 0.0 will record nothing.
"""
function start(; sample_rate::Real)
ccall(:jl_start_alloc_profile, Cvoid, (Cdouble,), Float64(sample_rate))

_g_sample_rate[] = sample_rate
_g_gc_num_before[] = Base.gc_num()
end

"""
Expand All @@ -89,15 +88,6 @@ Stop recording allocations.
"""
function stop()
ccall(:jl_stop_alloc_profile, Cvoid, ())

# increment a counter of how many allocs we would expect
# the memory profiler to see, based on how many allocs
# actually happened.
gc_num_after = Base.gc_num()
gc_diff = Base.GC_Diff(gc_num_after, _g_gc_num_before[])
alloc_count = Base.gc_alloc_count(gc_diff)
expected_samples = alloc_count * _g_sample_rate[]
_g_expected_sampled_allocs[] += expected_samples
end

"""
Expand All @@ -107,8 +97,6 @@ Clear all previously profiled allocation information from memory.
"""
function clear()
ccall(:jl_free_alloc_profile, Cvoid, ())

_g_expected_sampled_allocs[] = 0
return nothing
end

Expand All @@ -120,25 +108,7 @@ objects which can be analyzed.
"""
function fetch()
raw_results = ccall(:jl_fetch_alloc_profile, RawResults, ())
decoded_results = decode(raw_results)

# avoid divide-by-0 errors
if _g_expected_sampled_allocs[] > 0
missed_allocs = max(0, _g_expected_sampled_allocs[] - length(decoded_results.allocs))
missed_percentage = max(0, round(Int, missed_allocs / _g_expected_sampled_allocs[] * 100))
if missed_percentage > 0
@warn("The allocation profiler is not fully implemented, and missed approximately" *
" $(missed_percentage)% (estimated $(round(Int, missed_allocs)) / $(round(Int,
_g_expected_sampled_allocs[]))) " *
"of sampled allocs in the last run. " *
"For more info see https://github.com/JuliaLang/julia/issues/43688")
else
@warn("The allocation profiler is not fully implemented, and may have missed" *
" some of the allocs. " *
"For more info see https://github.com/JuliaLang/julia/issues/43688")
end
end
return decoded_results
return decode(raw_results)
end

# decoded results
Expand Down
25 changes: 0 additions & 25 deletions stdlib/Profile/test/allocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -111,31 +111,6 @@ end
Allocs.clear()
end

@testset "alloc profiler warning message" begin
@testset "no allocs" begin
Profile.Allocs.clear()
Profile.Allocs.fetch()
end
@testset "catches all allocations" begin
foo() = []
precompile(foo, ())
Profile.Allocs.clear()
Profile.Allocs.@profile sample_rate=1 foo()
# Fake that we expected exactly 1 alloc, since we should have recorded >= 1
Profile.Allocs._g_expected_sampled_allocs[] = 1
@assert length(Profile.Allocs.fetch().allocs) >= 1
end
@testset "misses some allocations" begin
foo() = []
precompile(foo, ())
Profile.Allocs.clear()
Profile.Allocs.@profile sample_rate=1 foo()
# Fake some allocs that we missed, to force the print statement
Profile.Allocs._g_expected_sampled_allocs[] += 10
@assert 1 <= length(Profile.Allocs.fetch().allocs) < 10
end
end

@testset "alloc profiler catches strings" begin
Allocs.@profile sample_rate=1 "$(rand())"

Expand Down

0 comments on commit 81b64c2

Please sign in to comment.