# Define a macro based on @timeit from TimerOutputs.jl

**URL:** https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577
**Category:** General Usage
**Tags:** question
**Created:** [November 13, 2024, 10:06am UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577 "2024-11-13T10:06:37Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![IvanBioli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivanbioli/32/213050_2.png) [@IvanBioli](https://discourse.julialang.org/u/IvanBioli)
#### Post date: [November 13, 2024, 10:06am UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/1 "2024-11-13T10:06:38Z")

</div>

Hi everyone,

I am using `TimerOutputs.jl` to time parts of my code with the `@timeit` macro. The typical syntax looks like this:

```julia
using TimerOutputs
timer = TimerOutput()

@timeit timer "some_identifier" begin
    # some code...
end

```

I would like to create a new macro called `@my_timeit` that behaves as follows:

- Uses `@timeit` from `TimerOutputs.jl` when `timer` is a `TimerOutput` instance.
- Executes the code block directly (without timing) if `timer == nothing`.

My questions are:

1. Is it possible to define such a macro in Julia?
2. If it is, would calling `@my_timeit nothing "some_identifier" begin ... end` add any overhead to the execution of `somecode...`?

Thanks in advance for any guidance or suggestions!

---

<div class="post-metadata">

### Author: ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)
#### Post date: [November 13, 2024, 11:26am UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/2 "2024-11-13T11:26:22Z")

</div>

There was [a proposal](https://github.com/KristofferC/TimerOutputs.jl/pull/109) for adding something like this to TimerOutputs.jl a few years ago, but it was never merged. But defining a separate macro as you propose may also work, I haven’t tried that.

---

<div class="post-metadata">

### Author: ![IvanBioli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivanbioli/32/213050_2.png) [@IvanBioli](https://discourse.julialang.org/u/IvanBioli)
#### Post date: [November 13, 2024, 12:15pm UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/3 "2024-11-13T12:15:52Z")

</div>

If I need to time a function I can simply use a wrapper like this:

```julia
import TimerOutputs

function wrap_with_timer(f::Function, name::String, timer::Union{TimerOutput,Nothing})
    if isnothing(timer)
        return f
    else
        f_(args...; kwargs...) = @timeit timer name f(args...; kwargs...)
        return f_
    end
end

```

My problem is now just with blocks of codes (which I don’t want to convert to a function)

---

<div class="post-metadata">

### Author: ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)
#### Post date: [November 13, 2024, 12:22pm UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/4 "2024-11-13T12:22:52Z")

</div>

This seems to work:

```julia
macro my_timeit(timer, label, expr)
    quote
        if $(esc(timer)) === nothing
            $(esc(expr))
        else
            @timeit $(esc(timer)) $(esc(label)) $(esc(expr))
        end
    end
end

```

The branch seems to be optimised away by the compiler, so using `timer = nothing` is as fast as simply running the expression without `@timeit`.

---

<div class="post-metadata">

### Author: ![IvanBioli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ivanbioli/32/213050_2.png) [@IvanBioli](https://discourse.julialang.org/u/IvanBioli)
#### Post date: [November 13, 2024, 2:40pm UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/5 "2024-11-13T14:40:19Z")

</div>

Thanks, it works perfectly! Any way to extend it to function definitions without my wrapper (the wrapper above creates problem with `@my_timeit`)?

---

<div class="post-metadata">

### Author: ![jipolanco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jipolanco/32/12129_2.png) [@jipolanco](https://discourse.julialang.org/u/jipolanco)
#### Post date: [November 13, 2024, 3:19pm UTC](https://discourse.julialang.org/t/define-a-macro-based-on-timeit-from-timeroutputs-jl/122577/6 "2024-11-13T15:19:12Z")

</div>

Not sure if I understood correctly, but the following variant allows annotating functions (there might be better ways of doing this):

```julia
macro my_timeit(timer, f)
    f.head === :function || error("expected a function")
    call = f.args[1]
    @assert call.head === :call # e.g. :(f(x))
    label = string(call.args[1]) # e.g. "f"
    expr = f.args[2] # actual content of the function
    @assert expr.head === :block
    # Replace function content
    f.args[2] = quote
        if $timer === nothing
            $expr
        else
            @timeit $timer $label $expr
        end
    end
    f
end

```

This can be used as:

```julia
@my_timeit timer function f(x, y, ..., timer)
    # stuff...
end

```
