-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix bug in @time
compilation time measurement, using _tryfinally macro.
#41923
Conversation
For a more complete history:
BUT, multithreading / concurrency of course is here to make everything worse. The approach taken in #39133 was reasonable if there's only ever a single Task on a single Thread. If you're in the middle of a But in a multithreaded world, where people are putting In the following two PRs, we attempted to fix this by using a different version of
@JeffBezanson said we would prefer the second approach, since If we think we can make progress on #39217 in a relatively short timescale, that's excellent! :) But in the meantime, this PR attempts to fix the bug in an expedient way that we know will currently work, while we wait for the better solution. Does that sound reasonable? Thanks for your help! :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This patch strikes me as a good stopgap solution and seems ready to go. (I am a bit biased though, having been involved in the scheming of this patch, so perhaps at least one neutral party should sign off as well. And perhaps Jeff in particular, given he had reservations about committing a patch like this previously. Maybe @vchuravy would like to take a look, what with #41762 (comment)? :))
Looks like a conflict has crept in --- perhaps rebase @NHDaly? :) |
2ec7f8d
to
0d02c59
Compare
I've marked this PR for Please see my description in the comment above, which explains why we are trying this approach again: Thanks! |
elapsedtime = time_ns() - elapsedtime | ||
local val = @__tryfinally($(esc(ex)), | ||
(elapsedtime = time_ns() - elapsedtime; | ||
compile_elapsedtime = cumulative_compile_time_ns_after() - compile_elapsedtime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the order of these be switched to avoid the possibility of compile time being more than 100%?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, Oscar made the point that we care more about an accurate elapsed time than about compile time fraction, so maybe it's ok.
Ok, I will stop being a purist about this and this can be merged :) |
Awesome, thanks @JeffBezanson! Sorry I didn't make |
tester_freebsd64 is doing its thing, i.e. failing in various seemingly unrelated ways. The tester_linux32 failures seem to be Profile-related; not sure what to make of those. |
Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time. Rename `@tryfinally` to `@_tryfinally` since it shouldn't be used. And add note that it's deprecated and should not be used
0d02c59
to
171d7f0
Compare
I hope you don't mind Nathan: I took the liberty of rebasing this pull request (in anticipation of merge) given it's a couple weeks stale and to check whether the tester_linux32 failure occurs again :). |
_amazing_ - not at all. Thank you Sacha, I really appreciate it! :)
…On Thu, Sep 16, 2021, 5:38 PM Sacha Verweij ***@***.***> wrote:
I hope you don't mind Nathan: I took the liberty of rebasing this pull
request (in anticipation of merge) given it's a couple weeks stale and to
check whether the tester_linux32 failure occurs again :).
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#41923 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAMCIELOJZLSTVPYBBRLMCLUCJPVFANCNFSM5CMYWHPA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
…ro. (#41923) Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time. (cherry picked from commit 08e100b)
🙏 thanks @KristofferC and @Sacha0! |
…ro. (#41923) Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time.
…ro. (JuliaLang#41923) Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time.
…ro. (JuliaLang#41923) Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time.
…ro. (JuliaLang#41923) Use a tryfinally macro to ensure compile timer is closed, while maintaining scope. This fixes a bug where an exception thrown _anywhere_, on any Task on any thread, completely disables the compilation time measurement for any concurrently executing `@time` blocks, without warning the user about it. Here are some examples of the current, broken behavior: - Throwing (and catching) an exception disables compilation time measurement, even though the exception didn't escape, without warning the user - note 0 compilation time reported: ```julia julia> @time begin # The following exception disables compilation time measurement try throw("ha HAH!") catch end @eval module M ; f(x) = 2*x ; end @eval M.f(2) end 0.003950 seconds (2.17 k allocations: 170.093 KiB) 4 ``` - Throwing an exception while the first task is sleeping disables compilation time measurement, so this ends up incorrectly reporting 0 compilation time: ```julia julia> f(n) = begin # while we're sleeping, someone throws an exception somewhere else :'( sleep(n) @eval module M ; f(x) = 2*x ; end @eval M.f(2) end f (generic function with 1 method) julia> f(0) # warmup WARNING: replacing module M. 4 julia> @async @time f(5) Task (runnable) @0x000000010f2c0780 julia> throw("oh no sad") ERROR: "oh no sad" Stacktrace: [1] top-level scope @ REPL[9]:1 WARNING: replacing module M. 5.008401 seconds (1.92 k allocations: 120.515 KiB) ``` After this commit, both of those examples correctly report their compilation time.
This PR reopens @IanButterworth's PR #39138, because in the meantime we've discovered a bug in the
@time
macro that needs a mechanism like this in order to solve it.I'll describe the bug below. But first, some context:
tryfinally
is an intermediate form that shouldn't be used in source ASTs.Since the
@time
macro is currently broken without this change, and since we know that there is a mechanism on the way (via #39217) that will replace this, it seems to me (and @Sacha0) that this is an expedient solution to the existing bug, without baking-in a reference to the internal intermediate form that we need to maintain. I've left a note in the code that directly states that this macro is deprecated and should not be used, and that a replacement is coming. I've renamed it to@_tryfinally
to discourage its use. Hopefully that seems like a reasonable tradeoff to allow us to fix the bug in@time
compilation measurement?Thanks! :)
The PR description follows:
Use a _tryfinally macro to ensure compile timer is closed, while maintaining scope.
This fixes a bug where an exception thrown anywhere, on any Task on
any thread, completely disables the compilation time measurement for any
concurrently executing
@time
blocks, without warning the user about it.Here are some examples of the current, broken behavior:
measurement, even though the exception didn't escape, without warning
the user - note 0 compilation time reported:
compilation time measurement, so this ends up incorrectly reporting 0
compilation time:
After this commit, both of those examples correctly report their
compilation time.