Other than the difference in syntax, is there any essential difference between a combination of tic+toc and @elapsed? Any difference between what they return? The only difference described by the doc is as follows, which I don’t quite understand. Can anyone explain a bit?
instead returning the number of seconds it (i.e. @elapsed) took to execute as a floating-point number.
The all use the same basic functionality (see time_ns()), but provide a different user interface. @time displays the time (and other info), use @elapsed when instead of displaying it, you would like to use the value, eg to compile statistics, etc, but see
tic and toc save the info in the global state (of the task). I find @time and @elapsed cleaner, but YMMV. Also, it is very easy to implement a combination of @elapsed and @time, if for some reason you need both the time and the value (eg as a tuple).
In addition to @time, as @Tamas_Papp mentioned, there is also @timev, which displays even more detailed information (about memory allocations, the GC, etc.), that can help if you are trying to figure out a performance issue.
Thanks both of you for the suggestions. Now I see the difference. I have been using BenchmarkTools.jl too to have more detailed statistics. However, if I want to use @elapsed or @benchmark, I have to wrap up all I want to time in a function. That’s not very convenient. That’s why I think I have to resort to using tic() and toc() sometimes.
May I know what most of you do when trying to time a few lines of your code in a big project or a large module? Do you also wrap the lines you want to time in a function in order to use @elapsed or @benchmark? Thanks!
Thanks. This is very useful. One question - What is the breakdown of the time returned by @time? My understanding is the time returned by @time = compiling time + memory allocation time + computing time + GC time. Is it right?
I don’t think so. First, @time just returns the result of evaluating the expression, not the elapsed time. That is displayed. At least on 0.5, it prints the elapsed time and the allocations (as a count, and the total memory allocated).
For quick & dirty timing I use @time, twice, wrapping things in a function. I only care about the second result. I do this realizing that there could easily be ±20% sampling errors.
For anything more serious, I use BenchmarkTools.jl. Which is a great tool. For very little time investment (learning how to use it), you get very nice & consistent benchmarks. For something quick, I use seconds=3 to get three seconds worth of samples.
@elapsed just returns a single value, which, AFAIK, is wall time spent executing the expression (because time_ns() counts that). It is a very simple macro. You can read the source, eg using @edit @elapsed 1 or something like that.
bench = @benchmark $(esc(xs...))
t0 = bench.times
t1 = median(bench.times)
tm = round(Int64, 2/(1/t0 + 1/t1))
bench = @benchmark $(esc(xs...))
a = bench.allocs
m = bench.memory
# use values held in variables
a = 0.75
# Int64 harmonic mean of fastest and median
# total bytes, distinct allocations
Note that BenchmarkTools now has @btime and @belapsed, which are drop-in replacements for @time and @elapsed. (They take longer to run, however, because they spend some time collecting timing statistics, whereas @time and @elapsed only run the code once.)