Skip to content

Commit

Permalink
Introduce current_task_*_time_ns for non-racy continuous metrics
Browse files Browse the repository at this point in the history
for the running task only.
Other tasks report metrics that are non-continuous
but updated only on task switches.
  • Loading branch information
nickrobinson251 committed Oct 31, 2024
1 parent cb98456 commit 3b04759
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
31 changes: 28 additions & 3 deletions base/experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -511,13 +511,30 @@ See [`Base.Experimental.task_metrics`](@ref).
"""
function task_cpu_time_ns(t::Task)
t.metrics_enabled || return nothing
if t.last_started_running_at == 0
return Int(t.cpu_time_ns)
if t == current_task()
current_task_cpu_time_ns()
else
return Int(t.cpu_time_ns + (time_ns() - t.last_started_running_at))
return Int(t.cpu_time_ns)
end
end

"""
Base.Experimental.current_task_cpu_time_ns() -> Union{Int, Nothing}
Return the total nanoseconds that the current task `t` has spent running.
Like [`Base.Experimental.task_cpu_time_ns`](@ref), but returns an up-to-date value for the
currently running task, whereas `task_cpu_time_ns(t)` for another task `t` only updates when
`t` yields or completes.
"""
function current_task_cpu_time_ns()
t = current_task()
t.metrics_enabled || return nothing
# These metrics fields can't update while we're running.
# But since we're running we need to include the time since we last started running!
return Int(t.cpu_time_ns + (time_ns() - t.last_started_running_at))
end

"""
Base.Experimental.task_wall_time_ns(t::Task) -> Union{Int, Nothing}
Expand All @@ -541,4 +558,12 @@ function task_wall_time_ns(t::Task)
return Int(end_at - start_at)
end

"""
Base.Experimental.current_task_wall_time_ns() -> Union{Int, Nothing}
Report the total wall time that the current task has been running.
See [`Base.Experimental.task_wall_time_ns`](@ref) for more details.
"""
current_task_wall_time_ns() = task_wall_time_ns(current_task())

end # module
16 changes: 6 additions & 10 deletions test/threads_exec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1439,15 +1439,11 @@ end
schedule(t2)
yield()
@assert istaskstarted(t1) && !istaskdone(t2)
cpu1 = Base.Experimental.task_cpu_time_ns(t2)
wall1 = Base.Experimental.task_wall_time_ns(t2)
@test cpu1 > 0
@test wall1 > 0
schedule(t2, 1)
yield()
@assert istaskfailed(t2)
@test Base.Experimental.task_cpu_time_ns(t2) > cpu1
@test Base.Experimental.task_wall_time_ns(t2) > wall1
@test Base.Experimental.task_cpu_time_ns(t2) > 0
@test Base.Experimental.task_wall_time_ns(t2) > 0
finally
Base.Experimental.task_metrics(false)
end
Expand All @@ -1458,14 +1454,14 @@ end
last_cpu_time = Ref(typemax(Int))
last_wall_time = Ref(typemax(Int))
t = Threads.@spawn begin
cpu_time = Base.Experimental.task_cpu_time_ns(current_task())
wall_time = Base.Experimental.task_wall_time_ns(current_task())
cpu_time = Base.Experimental.current_task_cpu_time_ns()
wall_time = Base.Experimental.current_task_wall_time_ns()
for _ in 1:5
x = time_ns()
while time_ns() < x + 100
end
new_cpu_time = Base.Experimental.task_cpu_time_ns(current_task())
new_wall_time = Base.Experimental.task_wall_time_ns(current_task())
new_cpu_time = Base.Experimental.current_task_cpu_time_ns()
new_wall_time = Base.Experimental.current_task_wall_time_ns()
@test new_cpu_time > cpu_time
@test new_wall_time > wall_time
cpu_time = new_cpu_time
Expand Down

0 comments on commit 3b04759

Please sign in to comment.