Modifying the @time macro

In my example case the macro @time

@time (for n in 0:100 myFunction(n) end)

outputs

0.355005 seconds (8 allocations: 1.188 KB)

I would like to have a macro @Time which outputs

(for n in 0:100 myFunction(n) end)
0.355005 seconds (8 allocations: 1.188 KB)

In other words @Time prints the argument of @time
and the result of @time. I have read the docs on
metaprogramming however did not succeed in writing
this macro. Any help?

Something like

macro time2(ex)
    quote
        local stats = Base.gc_num()
        local elapsedtime = time_ns()
        local val = $(esc(ex))
        elapsedtime = time_ns() - elapsedtime
        local diff = Base.GC_Diff(Base.gc_num(), stats)
        println($(Meta.quot(ex))) # print
        Base.time_print(elapsedtime, diff.allocd, diff.total_time,
                        Base.gc_alloc_count(diff))
        val
    end
end

Note that most of the body is from the definition of @time (which you can look up with eg @edit), I just inserted a line for printing and qualified some functions from Base with their module name.

Combining the @show and @time macro, with some modifications:

julia> macro showtime(ex)
           println(sprint(Base.show_unquoted, ex))
           @time ex
       end

I don’t think this does what the OP asked for — it will print ex at the time of macro expansion, and return the value otherwise. If the intention is to reuse @time, consider

macro time2(ex)
    quote
        println($(Meta.quot(ex)))
        @time $ex
    end
end
1 Like

Ah, right, I updated my example such that it also works.
Edit: It doesnt. Your example is better :smiley:

$ex has to be escaped…

Thanks Tamas, however

macro time2(ex)
    quote
        println($(Meta.quot(ex)))
        @time esc($(ex))
    end
end
myfunc(n::Int) = sleep(0.00001*n)
@time2 (for n in 0:100 myfunc(n) end)

outputs

for n = 0:100 # long\path\...\myfunc.jl, line 15:
    myFunc(n)
end
0.199292 seconds (612 allocations: 37.984 KB)

The problem here is the comment

# long\path\...\myfunc.jl, line 15:

which I do not want. How can I get rid of it?

$(esc(ex)) (not about line node filtering)

using MacroTools
macro time2(ex)
    quote
        println($(Meta.quot(rmlines(ex))))
        @time $(esc(ex))
    end
end

Look at MacroTools.jl, it is a really great package with lots of wonderful utilities like this.

3 Likes

Hmm… this does not make any difference
to what I described in this post.

Works perfectly for me.

To make sure that it is not an issue with my installation
I run the same code on SageMathCloud in a notebook.

Instead of the comment as it appears on my computer

# long\path\...\myfunc.jl, line 15:

I now see at the corresponding position

# In[1], line 11:

Insignificant differences aside this shows that
that the problem is not a mirage.

The solution listed here didn’t work for my case because of some complicated way escaping was happening which I never figured out. Anyway I ended up using macroexpand directly and the escaping issues went away. Here is how to use macroexpand in cases like this.

macro time2(expr)
  macroexpand(__module__, Expr(:macrocall, getfield(Main, Symbol("@time")), __source__, expr))
end

You can also use SyntaxTree.linefilter! from my package, which is faster, if you need a performance critical tool that removes the line comnets from Julia expressions.