diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 3c3b6cb65ad00..ffcc6ad10b05a 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -560,28 +560,33 @@ function tree!(root::StackFrameTree{T}, all::Vector{UInt64}, lidict::Union{LineI return root end -# Print a "branch" starting at a particular level. This gets called recursively. -function tree(io::IO, bt::StackFrameTree, level::Int, cols::Int, fmt::ProfileFormat, noisefloor::Int) - level > fmt.maxdepth && return - isempty(bt.down) && return - # Order the line information - nexts = collect(values(bt.down)) - lilist = collect(frame.frame for frame in nexts) - counts = collect(frame.count for frame in nexts) - # Generate the string for each line - strs = tree_format(lilist, counts, level, cols) - # Recurse to the next level - for i in liperm(lilist) - down = nexts[i] - count = down.count - count < fmt.mincount && continue - count < noisefloor && continue - str = strs[i] - println(io, isempty(str) ? "$count unknown stackframe" : str) - noisefloor_down = fmt.noisefloor > 0 ? floor(Int, fmt.noisefloor * sqrt(count)) : 0 - tree(io, down, level + 1, cols, fmt, noisefloor_down) +# Print the stack frame tree starting at a particular root. Uses a worklist to +# avoid stack overflows. +function tree(io::IO, bt::StackFrameTree, cols::Int, fmt::ProfileFormat) + worklist = [(bt, 0, 0, "")] + while !isempty(worklist) + (bt, level, noisefloor, str) = popfirst!(worklist) + isempty(str) || println(io, str) + level > fmt.maxdepth && continue + isempty(bt.down) && continue + # Order the line information + nexts = collect(values(bt.down)) + lilist = collect(frame.frame for frame in nexts) + counts = collect(frame.count for frame in nexts) + # Generate the string for each line + strs = tree_format(lilist, counts, level, cols) + # Recurse to the next level + for i in reverse(liperm(lilist)) + down = nexts[i] + count = down.count + count < fmt.mincount && continue + count < noisefloor && continue + str = strs[i] + isempty(str) && (str = "$count unknown stackframe") + noisefloor_down = fmt.noisefloor > 0 ? floor(Int, fmt.noisefloor * sqrt(count)) : 0 + pushfirst!(worklist, (down, level + 1, noisefloor_down, str)) + end end - nothing end function tree(io::IO, data::Vector{UInt64}, lidict::Union{LineInfoFlatDict, LineInfoDict}, cols::Int, fmt::ProfileFormat) @@ -594,8 +599,7 @@ function tree(io::IO, data::Vector{UInt64}, lidict::Union{LineInfoFlatDict, Line warning_empty() return end - level = 0 - tree(io, root, level, cols, fmt, 0) + tree(io, root, cols, fmt) nothing end