Essentially, I was playing with code_native(), being curious what kind of code Julia generates for easy to optimize stuff. The extra code generated by @assert was a surprise, and seemed like it ought to cause significant overhead. The timings were pretty much an afterthought, and I did them simply with @time.
Now that I tried timing it a bit more seriously, I found that it's difficult. The variances in timing something as fast as this are enormous relative to the average time. Julia also does more inlining than I thought, so in practice the extra instructions may not matter too much after all.
FWIW, this version of myassert is closer to the standard one, and still produces short assembly:
macro myassert(ex,msg...)
msg = isempty(msg) ? string(ex) : esc(msg[1])
:($(esc(ex)) ? nothing : _assert($msg))
end
function _assert(x) # @noinline would be nice
error("assertion failed: ", x)
nothing
end
The modifications are:
1. Turn ex into a string compile-time instead of run-time.
2. De-inline two-argument call to error(). One-argument call is less expensive, maybe because error() uses varargs for the multiargument case?
3. Return "nothing" after the error call. This is also required; I think this just prevents Julia from inlining _assert.