Skip to content

Commit

Permalink
win,Profile: fix timeout units (JuliaLang#38208)
Browse files Browse the repository at this point in the history
Previously, we were using units of seconds (rounded down) but the
function expected milliseconds. So this was effectively always zero
(ignored) in the computation.

Empirically, the documentation for Sleep is fundamentally incorrect, and
the stated advice to add `wPeriodMin` is bad. So here we remove that.
(Microsoft has given the thumbs up to this observation also now.)

Also update the Profile code defaults to sample for longer, and faster,
since only the Win32 stack-unwinder (dbghelp) is absurdly slow.

Co-authored-by: kimikage <kimikage.ceo@gmail.com>
  • Loading branch information
vtjnash and kimikage authored Nov 4, 2020
1 parent 1f9e8bd commit 09f96e1
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 10 deletions.
5 changes: 2 additions & 3 deletions src/signals-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,8 @@ static DWORD WINAPI profile_bt( LPVOID lparam )
}
timeBeginPeriod(tc.wPeriodMin);
while (1) {
DWORD timeout = nsecprof / GIGA;
timeout += tc.wPeriodMin;
Sleep(timeout);
DWORD timeout_ms = nsecprof / (GIGA / 1000);
Sleep(timeout_ms > 0 ? timeout_ms : 1);
if (bt_size_cur < bt_size_max && running) {
JL_LOCK_NOGC(&jl_in_stackwalk);
jl_lock_profile();
Expand Down
9 changes: 6 additions & 3 deletions stdlib/Profile/src/Profile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ function init(n::Integer, delay::Real)
end

# init with default values
# Use a max size of 1M profile samples, and fire timer every 1ms
if Sys.iswindows()
# Use a max size of 10M profile samples, and fire timer every 1ms
# (that should typically give around 100 seconds of record)
if Sys.iswindows() && Sys.WORD_SIZE == 32
# The Win32 unwinder is 1000x slower than elsewhere (around 1ms/frame),
# so we don't want to slow the program down by quite that much
__init__() = init(1_000_000, 0.01)
else
__init__() = init(1_000_000, 0.001)
__init__() = init(10_000_000, 0.001)
end

"""
Expand Down
9 changes: 5 additions & 4 deletions stdlib/Profile/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,15 @@ end

@testset "setting sample count and delay in init" begin
n_, delay_ = Profile.init()
@test n_ == 1_000_000
def_delay = Sys.iswindows() ? 0.01 : 0.001
def_n = Sys.iswindows() && Sys.WORD_SIZE == 32 ? 1_000_000 : 10_000_000
@test n_ == def_n
def_delay = Sys.iswindows() && Sys.WORD_SIZE == 32 ? 0.01 : 0.001
@test delay_ == def_delay
Profile.init(n=1_000_001, delay=0.0005)
n_, delay_ = Profile.init()
@test n_ == 1_000_001
@test delay_ == 0.0005
Profile.init(n=1_000_000, delay=def_delay)
Profile.init(n=def_n, delay=def_delay)
end

@testset "Line number correction" begin
Expand Down Expand Up @@ -131,5 +132,5 @@ let cmd = Base.julia_cmd()
s = read(p, String)
close(t)
@test success(p)
@test parse(Int, s) > 1000
@test parse(Int, s) > 100
end

0 comments on commit 09f96e1

Please sign in to comment.