JuliaPerf / PProf.jl

Export Julia profiles to the pprof format
MIT License
154 stars 17 forks source link

PProf.Allocs.pprof is messing up some frames. #69

Closed NHDaly closed 1 year ago

NHDaly commented 1 year ago

We've had a suspicion of this for a while, but i've never managed to catch it in such a small profile as this one, where there's definitive proof! :)

Here's the original export from Profile.Allocs.fetch(), which is correct: Profile.Allocs.fetch.zip And here's the incorrect output from PProf: alloc-profile.pb.gz

There are three incorrect frames, indicated by the Arrows:

Screen Shot 2022-10-01 at 12 55 49 PM

You can see from printing the raw data, that these should actually be:

I'm not sure what's gone wrong, but it's validating to know that we've finally got a reproducer! :)

NHDaly commented 1 year ago

Dum Dum DUMMMMMMMMMMMMMMMM!!

julia> fr1 = f.allocs[2].stacktrace[4]
get!(func::RelationalAITypes.var"#107#108"{DataType}, cache::MultiThreadedCaches.MultiThreadedCache{Type, UInt64}, key::Type)

julia> fr3 = f.allocs[2].stacktrace[10]
mutts_hash(v::Vector{RelationalAITypes.WrappedType}, h::UInt64)

julia> hash(fr1)
0x2611c607ad495a8c

julia> hash(fr3)
0x2611c607ad495a8c

julia> fr3 == fr1
true

What the heck you guys!?

NHDaly commented 1 year ago

Aha! It turns out it's because comparing StackFrames apparently skips the linfo and pointer, even though apparently also sometimes a StackFrame can be empty other than the linfo and pointer!!! 😮 Is this a bug worth reporting to julia?

https://github.com/JuliaLang/julia/blob/00646634c6a73998eaae3785eb78fea881c39502/base/stacktraces.jl#L80-L96

#=
If the StackFrame has function and line information, we consider two of them the same if
they share the same function/line information.
=#
function ==(a::StackFrame, b::StackFrame)
    return a.line == b.line && a.from_c == b.from_c && a.func == b.func && a.file == b.file && a.inlined == b.inlined # excluding linfo and pointer
end

function hash(frame::StackFrame, h::UInt)
    h += 0xf4fbda67fe20ce88 % UInt
    h = hash(frame.line, h)
    h = hash(frame.file, h)
    h = hash(frame.func, h)
    h = hash(frame.from_c, h)
    h = hash(frame.inlined, h)
    return h
end

And indeed, in this case:

julia> fr3.func
Symbol("")

julia> fr1.func
Symbol("")

julia> fr1.line
-1

julia> fr3.line
-1

julia> fr3.file
Symbol("")

julia> fr1.file
Symbol("")

julia> fr3.inlined
false

julia> fr1.inlined
false

(I'm not sure why that stuff is all missing!?)

nickrobinson251 commented 1 year ago

Is this a bug worth reporting to julia?

Seems odd to me -- at least worth an issue asking why this is so?

NHDaly commented 1 year ago

Hokay, i've asked about it here!: https://github.com/JuliaLang/julia/issues/47028