Skip to content

Commit

Permalink
Merge pull request #24 from vilterp/pv-compiler-timings-lock-backcompat
Browse files Browse the repository at this point in the history
make new timing change backward-compatible
  • Loading branch information
vilterp committed Dec 3, 2022
2 parents 1e62871 + ce8bb69 commit 8cf3a57
Showing 1 changed file with 48 additions and 9 deletions.
57 changes: 48 additions & 9 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ end

_typeinf_identifier(frame::InferenceFrameInfo) = frame

_typeinf_frame_linfo(frame::Core.Compiler.InferenceState) = frame.linfo
_typeinf_frame_linfo(frame::InferenceFrameInfo) = frame.mi

"""
Core.Compiler.Timings.Timing(mi_info, start_time, ...)
Expand Down Expand Up @@ -97,16 +100,49 @@ const _finished_timings = Timing[]
# because we create a new node for duplicates.)
const _timings = Timing[]

# ROOT() is an empty function used as the top-level Timing node to measure all time spent
# *not* in type inference during a given recording trace. It is used as a "dummy" node.
function ROOT() end
const ROOTmi = Core.Compiler.specialize_method(
first(Core.Compiler.methods(ROOT)), Tuple{typeof(ROOT)}, Core.svec())
"""
Core.Compiler.reset_timings()
Empty out the previously recorded type inference timings (`Core.Compiler._timings`), and
start the ROOT() timer again. `ROOT()` measures all time spent _outside_ inference.
DEPRECATED: this will be removed; use `clear_and_fetch_timings` instead.
"""
function reset_timings()
empty!(_timings)
push!(_timings, Timing(
# The MethodInstance for ROOT(), and default empty values for other fields.
InferenceFrameInfo(ROOTmi, 0x0, Any[], Any[Core.Const(ROOT)], 1),
_time_ns()))
return nothing
end

# (This is split into a function so that it can be called both in this module, at the top
# of `enter_new_timer()`, and once at the Very End of the operation, by whoever started
# the operation and called `reset_timings()`.)
# NOTE: the @inline annotations here are not to make it faster, but to reduce the gap between
# timer manipulations and the tasks we're timing.
@inline function close_current_timer()
stop_time = _time_ns()
parent_timer = _timings[end]
accum_time = stop_time - parent_timer.cur_start_time

# Add in accum_time
@inbounds begin
_timings[end].time += accum_time
end
return nothing
end

@inline function enter_new_timer(frame)
# Very first thing, stop the active timer: get the current time and add in the
# time since it was last started to its aggregate exclusive time.
if length(_timings) > 0
stop_time = _time_ns()
parent_timer = _timings[end]
accum_time = stop_time - parent_timer.cur_start_time

# Add in accum_time
parent_timer.time += accum_time
close_current_timer()
end

# Start the new timer right before returning
Expand All @@ -131,15 +167,18 @@ end
# Finish the new timer
stop_time = _time_ns()

expected_mi_info = _typeinf_identifier(_expected_frame_)
expected_linfo = _typeinf_frame_linfo(_expected_frame_)

# 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
new_timer = pop!(_timings)
Core.Compiler.@assert new_timer.mi_info.mi === expected_mi_info.mi
Core.Compiler.@assert new_timer.mi_info.mi === expected_linfo

is_profile_root = length(_timings) === 0
# check for two cases: normal case & backcompat case
is_profile_root_normal = length(_timings) === 0
is_profile_root_backcompat = length(_timings) === 1 && _timings[1] === ROOTmi
is_profile_root = is_profile_root_normal || is_profile_root_backcompat

accum_time = stop_time - new_timer.cur_start_time
# Add in accum_time ("modify" the immutable struct)
Expand Down

0 comments on commit 8cf3a57

Please sign in to comment.