Skip to content
Merged
Changes from 18 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
88a504e
First pass at providing full inferrable set to SnoopCompile `@snoopi`
NHDaly Sep 11, 2020
a9d3d53
Use Array{Bool,0} to control snoopi "collect inference callees" feature
NHDaly Sep 11, 2020
97b5cde
Start recording dependency graph edges for snoopi
NHDaly Sep 14, 2020
be69119
Comment out old attempt
NHDaly Sep 14, 2020
c2640ae
Second attempt at per-method inference timings, this time by also all…
NHDaly Sep 17, 2020
516aabf
Undo commented out attempted ccall ptr for `typeinf()`
NHDaly Sep 17, 2020
490395b
Delete leftovers from previous attempt
NHDaly Sep 17, 2020
9b4bddc
Use a 0-dim array for `const _typeinf_function`.
NHDaly Sep 21, 2020
57801e0
Switch from `_apply_latest()` to `_apply_pure()` which works even ins…
NHDaly Sep 22, 2020
968bbdc
simplify array construction
NHDaly Sep 22, 2020
e8b40ff
Implement very basic nested timing in Core.Compiler.Timings
NHDaly Sep 25, 2020
bcd37f3
Add start_time to Core.Compiler.Timings to support profiles
NHDaly Sep 25, 2020
0f56376
Simplify Timing() constructor
NHDaly Sep 25, 2020
5b35567
Exclude snoop overhead from recursive per-method inference timings
NHDaly Sep 25, 2020
132ba91
Fix root timing: reset() sets current time instead of 0
NHDaly Sep 25, 2020
b30adcf
Performance-tweaking typeinf measurement overhead.
NHDaly Sep 30, 2020
388c747
Extract out enter_new_timer(name), exit_current_timer(_expected_name_…
NHDaly Sep 30, 2020
d79fbfc
Inline typeinf timing helper functions. Simplify __measure_typeinf__ …
NHDaly Oct 1, 2020
152a93f
Use at-inboudnds more consistently in Core.Compiler.Timings
NHDaly Oct 5, 2020
3289266
Fix close_current_timer() "root" timings. Add comments.
NHDaly Oct 6, 2020
028e15d
Switch to recording MethodInstance, and world, in Core.Compiler.Timings.
NHDaly Oct 7, 2020
9954bfa
Record more information in typeinf timing:
NHDaly Oct 7, 2020
dde84b2
Add tests of basic typeinf time functionality introduced in #37749
NHDaly Oct 7, 2020
cb9da41
Merge remote-tracking branch 'origin/master' into nhd-snoopi-inferrab…
NHDaly Oct 8, 2020
b61a64a
Rename s/Core.Compiler.__toggle_measure_typeinf/Core.Compiler.__set_m…
NHDaly Oct 8, 2020
396ed33
Improve comments in base/compiler/typeinfer.jl
NHDaly Oct 9, 2020
32b7be0
Use a consistent type for Timings.mi_info (`Tuple{Core.MethodInstance…
NHDaly Oct 9, 2020
663f47f
Docstring, comment, and code cleanups from PR review
NHDaly Oct 10, 2020
f6f4705
PR feedback: use a Struct for snoopi info: InferenceFrameInfo
NHDaly Oct 12, 2020
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
127 changes: 127 additions & 0 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,134 @@ function typeinf(interp::AbstractInterpreter, result::InferenceResult, cached::B
return typeinf(interp, frame)
end

module Timings

using Core.Compiler: -, +, length, push!, pop!, @inline

struct Timing
name::Any
start_time::UInt64
cur_start_time::UInt64
time::UInt64
children::Core.Array{Timing,1}
Timing(name, start_time, cur_start_time, time, children) = new(name, start_time, cur_start_time, time, children)
Timing(name, start_time) = new(name, start_time, start_time, UInt64(0), Timing[])
end

time_ns() = ccall(:jl_hrtime, UInt64, ())

const _timings = Timing[]
function reset_timings()
Core.Compiler.empty!(_timings)
Core.Compiler.push!(_timings, Timing("root", time_ns()))
nothing
Comment thread
NHDaly marked this conversation as resolved.
Outdated
end
reset_timings()

function close_current_timer()
stop_time = time_ns()
parent_timer = _timings[end]
Comment thread
NHDaly marked this conversation as resolved.
accum_time = Core.Compiler.:(-)(stop_time, parent_timer.cur_start_time)
end

@inline function enter_new_timer(name)
# Stop the current timer before recursing into the child
stop_time = Timings.time_ns()

_timings = Timings._timings
parent_timer = _timings[end]
accum_time = stop_time - parent_timer.cur_start_time

# Add in accum_time ("modify" the immutable struct)
_timings[end] = Timings.Timing(
parent_timer.name,
parent_timer.start_time,
parent_timer.cur_start_time,
parent_timer.time + accum_time,
parent_timer.children,
)

# Start the new timer right before returning
push!(_timings, Timings.Timing(name, UInt64(0)))
len = length(_timings)
new_timer = _timings[len]
# Set the current time _after_ appending the node, to try to exclude the
# overhead from measurement.
start = Timings.time_ns()

Core.Compiler.@inbounds begin
_timings[len] = Timings.Timing(
new_timer.name,
start,
start,
new_timer.time,
new_timer.children,
)
end

# IDEA:
# _timings_values[end] = Timings.time_ns()
end

@inline function exit_current_timer(_expected_name_)
# Finish the new timer
stop_time = Timings.time_ns()

# Grab the new timer again because it might have been modified in _timings
# (since it's an immutable struct)
# And remove it from the current timings stack
_timings = Timings._timings
new_timer = pop!(_timings)
Core.Compiler.@assert new_timer.name === _expected_name_ (new_timer.name, _expected_name_)

accum_time = stop_time - new_timer.cur_start_time
# Add in accum_time ("modify" the immutable struct)
new_timer = Timings.Timing(
new_timer.name,
new_timer.start_time,
new_timer.cur_start_time,
new_timer.time + accum_time,
new_timer.children
)
# Record the final timing with the original parent timer
parent_timer = _timings[end]
push!(parent_timer.children, new_timer)

# And finally restart the parent timer:
len = length(_timings)
Core.Compiler.@inbounds begin
_timings[len] = Timings.Timing(
parent_timer.name,
parent_timer.start_time,
Timings.time_ns(),
parent_timer.time,
parent_timer.children,
)
end
end


end # module Timings

# TODO(PR): What's the right way to do a global const mutable boolean in Core.Compiler?
const __measure_typeinf__ = fill(false)
__toggle_measure_typeinf(onoff::Bool) = __measure_typeinf__[] = onoff

function typeinf(interp::AbstractInterpreter, frame::InferenceState)
if __measure_typeinf__[]
Timings.enter_new_timer(frame.linfo.specTypes)
Comment thread
NHDaly marked this conversation as resolved.
Outdated

Comment thread
NHDaly marked this conversation as resolved.
Outdated
v = _typeinf(interp, frame)

Timings.exit_current_timer(frame.linfo.specTypes)

return v
else
return _typeinf(interp, frame)
end
end

function _typeinf(interp::AbstractInterpreter, frame::InferenceState)
typeinf_nocycle(interp, frame) || return false # frame is now part of a higher cycle
# with no active ip's, frame is done
frames = frame.callers_in_cycle
Expand Down