diff --git a/doc/src/manual/profile.md b/doc/src/manual/profile.md index 91b3c34a4fb20e..c3dc1ca090a46f 100644 --- a/doc/src/manual/profile.md +++ b/doc/src/manual/profile.md @@ -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 diff --git a/stdlib/Profile/src/Allocs.jl b/stdlib/Profile/src/Allocs.jl index eb75775ff7a351..1285d4b430f4c1 100644 --- a/stdlib/Profile/src/Allocs.jl +++ b/stdlib/Profile/src/Allocs.jl @@ -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) @@ -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))) @@ -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 """ @@ -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 """ @@ -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 @@ -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 diff --git a/stdlib/Profile/test/allocs.jl b/stdlib/Profile/test/allocs.jl index 4eae5b0cf68c19..b8d6222d075674 100644 --- a/stdlib/Profile/test/allocs.jl +++ b/stdlib/Profile/test/allocs.jl @@ -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())"