# Macro for counting the number of times a function is called?

**URL:** https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129
**Category:** New to Julia
**Created:** [April 9, 2017, 4:25pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129 "2017-04-09T16:25:39Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![sdwfrost](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdwfrost/32/2831_2.png) [@sdwfrost](https://discourse.julialang.org/u/sdwfrost)
#### Post date: [April 9, 2017, 4:25pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/1 "2017-04-09T16:25:39Z")

</div>

Dear All,

I’m trying to count the number of times a function is called; rather than assign a global variable by hand inside each function, it makes sense to use a macro. The instrumenting profiler can do this, but it seems overkill for what I want. Any tips on how best to do this?

Best  
Simon

---

<div class="post-metadata">

### Author: ![dfdx](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dfdx/32/120_2.png) [@dfdx](https://discourse.julialang.org/u/dfdx)
#### Post date: [April 9, 2017, 7:31pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/2 "2017-04-09T19:31:02Z")

</div>

Try this:

```julia
const COUNTERS = Dict{String, Int}()

macro counted(f)
    name = f.args[1].args[1]
    name_str = String(name)
    body = f.args[2]
    counter_code = quote
        if !haskey(COUNTERS, $name_str)
            COUNTERS[$name_str] = 0
        end
        COUNTERS[$name_str] += 1
    end
    insert!(body.args, 1, counter_code)
    return f
end

@counted inc(x) = x + 1

inc(5)
inc(42)
inc(18)

COUNTERS["inc"] # ==> 3

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [April 11, 2017, 7:45am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/3 "2017-04-11T07:45:14Z")

</div>

And a non-macro solution:

```julia
type Counting{TF}
    f::TF
    counter::Int
end

Counting(f) = Counting(f, 0)

function (c::Counting)(args...)
    c.counter += 1
    c.f(args...)
end

cf = Counting(identity)

[cf(i) for i in 1:10]

cf.counter

```

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [April 11, 2017, 10:23am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/4 "2017-04-11T10:23:14Z")

</div>

@Tamas_Papp nice solution!  
I’d add one minor thing, to underline the fact that you can use this like the real function with almost no downsides:

```julia
type Counting{TF} <: Function # inherit from function, to integrate better with e.g. map
    f::TF
    counter::Int
end
# Define the function you want to count like this:
const my_function = Counting() do args...
  # my function body
end
# use as like any other julia function
map(my_function, rand(10))

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [April 11, 2017, 10:58am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/5 "2017-04-11T10:58:16Z")

</div>

[GitHub - KristofferC/TimerOutputs.jl: Formatted output of timed sections in Julia](https://github.com/KristofferC/TimerOutputs.jl) can do this but perhaps it is overkill for this situation.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [April 11, 2017, 11:14am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/6 "2017-04-11T11:14:28Z")

</div>

You don’t need to make the type `<: Function` to work with `map`. Cf a question I asked recently:

> [@Functions and callable methods](https://discourse.julialang.org/t/functions-and-callable-methods/2983):
>
> I am confused about how to organize my code for objects which behave like functions. Some functions do different things when called with arguments which are \<: Function, eg Plots.plot will plot the function, but will not plot a callable object which is not \<: Function (because it can’t dispatch on it, unless a recipe is defined etc). Generally, a type T can have (f::T)(...) methods defined, and T \<: Function can hold. Apparently these two are orthogonal, one can have a \<: Function without i…

---

<div class="post-metadata">

### Author: ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)
#### Post date: [April 11, 2017, 11:15am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/7 "2017-04-11T11:15:35Z")

</div>

Yeah map is a bad example, since it’s actually not typed that way… But there are definitely other functions where that’d be the case

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [July 19, 2017, 6:33pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/8 "2017-07-19T18:33:00Z")

</div>

@kristoffer.carlsson That sounds like a powerful solution but how do you do it generically? I’m trying to do something like

```julia
const timer = TimerOutput()
for fun in (:f, :g, :h)
  fname = Symbol("timed_$(fun)")
  @eval $(fname)(args...) = :(@timeit timer string($(fun)) $fun(args...))
end

```

but it’s not quite right. Thanks!

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [July 19, 2017, 7:33pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/9 "2017-07-19T19:33:25Z")

</div>

```julia
julia> using TimerOutputs

julia> const timer = TimerOutput();

julia> for fun in (:f, :g, :h)
              fname = Symbol("timed_$(fun)")
              @eval $(fname)(args...) = @timeit timer string($(fun)) $fun(args...)
          end

julia> f(x) = x
f (generic function with 1 method)

julia> timed_f(2)
2

julia> timer
 ──────────────────────────────────────────────────────────────────
                           Time Allocations      
                   ────────────────────── ───────────────────────
 Tot / % measured: 2.89s / 0.05% 11.8MiB / 0.01%    

 Section ncalls time %tot avg alloc %tot avg
 ──────────────────────────────────────────────────────────────────
 f 1 1.38ms 100% 1.38ms - 100% -
 ──────────────────────────────────────────────────────────────────

```

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [July 19, 2017, 9:32pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/10 "2017-07-19T21:32:48Z")

</div>

Yes, that works, thank you. The extra quote level was because I was fiddling to get something like this to work:

```julia
type Thing
  fs::Vector{Function}
  timer::TimerOutput
end

function Thing(funs::Symbol...)
  timed_funs = Function[]
  timer = TimerOutput()
  for fun in funs
    fname = Symbol("timed_$(fun)")
    @eval begin
      $(fname)(args...) = @timeit timer string($(fun)) $fun(args...)
      push!($(timed_funs), $(fname))
    end
  end
  return Thing(timed_funs, timer)
end

```

Somehow, the timed functions have lost track of `timer`:

```julia
julia> f(x) = x; g(x) = x+1; h(x) = x+2;

julia> thing = Thing(:f, :g, :h);

julia> [f(1) for f in thing.fs]
ERROR: UndefVarError: timer not defined

```

I’d rather not pass `timer` as argument to the constructor because I’d like to have several `Thing`s, each with its own timer.  
I must be confused. I guess `@timeit` doesn’t quite behave like a closure?!

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [July 19, 2017, 9:47pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/11 "2017-07-19T21:47:14Z")

</div>

`@eval` is done in global scope so it won’t have access to local variables.

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [July 19, 2017, 10:24pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/12 "2017-07-19T22:24:39Z")

</div>

Is a macro the only way to achieve what I’m trying to do then?

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [July 19, 2017, 10:33pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/13 "2017-07-19T22:33:41Z")

</div>

My thinking is if you want to have a function reference a global variable you need to make the variable global.

So perhaps something like:

```julia
function Thing(funs::Symbol...)
  timed_funs = Function[]
  timerlabel = gensym()
  @eval const $timerlabel = TimerOutput()
  for fun in funs
    fname = Symbol("timed_$(fun)")
    @eval begin
      $(fname)(args...) = @timeit $(timerlabel) string($(fun)) $fun(args...)
      push!($(timed_funs), $(fname))
    end
  end
  return Thing(timed_funs, @eval $timerlabel)
end

```

giving

```julia
julia> f(x) = x; g(x) = x+1; h(x) = x+2;

julia> thing = Thing(:f, :g, :h);

julia> [f(1) for f in thing.fs]
3-element Array{Int64,1}:
 1
 2
 3

julia> thing.timer
 ──────────────────────────────────────────────────────────────────
                           Time Allocations      
                   ────────────────────── ───────────────────────
 Tot / % measured: 8.54s / 0.05% 14.0MiB / 0.02%    

 Section ncalls time %tot avg alloc %tot avg
 ──────────────────────────────────────────────────────────────────
 h 1 1.57ms 33.8% 1.57ms - 35.2% -
 g 1 1.56ms 33.6% 1.56ms - 35.2% -
 f 1 1.51ms 32.6% 1.51ms - 29.7% -
 ──────────────────────────────────────────────────────────────────

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [July 19, 2017, 10:43pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/14 "2017-07-19T22:43:53Z")

</div>

Note that if you want to timer to be exception safe you should use the `do` format:

```julia
timeit(to, "label") do
    # stuff
end

```

(will be slightly slower due to try catching)

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [July 20, 2017, 1:08am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/15 "2017-07-20T01:08:09Z")

</div>

Is this the right way to avoid global variables then?

```julia
julia> using TimerOutputs

julia> type Thing
       fs::Vector{Function}
       timer::TimerOutput
       end

julia> function Thing(fs::Function...)
       timer = TimerOutput()
       return Thing([(args...) -> @timeit timer "f" f(args...) for f in fs], timer)
       end
Thing

julia> f(x) = x; g(x) = x+1; h(x) = x+2;

julia> thing = Thing(f, g, h);

julia> [f(1) for f in thing.fs]
3-element Array{Int64,1}:
 1
 2
 3

julia> thing.timer
 ──────────────────────────────────────────────────────────────────
                           Time Allocations      
                   ────────────────────── ───────────────────────
 Tot / % measured: 18.9s / 0.02% 93.6MiB / 0.00%    

 Section ncalls time %tot avg alloc %tot avg
 ──────────────────────────────────────────────────────────────────
 f 3 3.53ms 100% 1.18ms 1.41KiB 100% -
 ──────────────────────────────────────────────────────────────────

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [July 20, 2017, 7:05am UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/16 "2017-07-20T07:05:45Z")

</div>

Yeah, storing a closure also works.

---

<div class="post-metadata">

### Author: ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)
#### Post date: [July 20, 2017, 3:28pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/17 "2017-07-20T15:28:32Z")

</div>

Thank you!

---

<div class="post-metadata">

### Author: ![karelispanagiotis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/karelispanagiotis/32/42748_2.png) [@karelispanagiotis](https://discourse.julialang.org/u/karelispanagiotis)
#### Post date: [October 27, 2022, 9:47pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/18 "2022-10-27T21:47:34Z")

</div>

I followed the instructions of the package but I could not get it to work. I want to track the number of function calls.

The function is defined inside a module and is being used by a variety of other modules. I am able to modify the code inside the module.

example code of my trial:

```julia
module MyModule 
const to = TimerOutput()

function myFunc()
    @timeit to "myFunc" begin 
        #normal computation of myFunc()
    end 
    return 
end

end

# code that uses other modules that use MyModule #

show(MyModule.to)

```

and the output is empty even though it counts time and allocations:

```julia
 ────────────────────────────────────────────────────────────────────
                            Time Allocations      
                   ─────────────────────── ────────────────────────
 Tot / % measured: 13.1s / 0.0% 1.48GiB / 0.0%    

 Section ncalls time %tot avg alloc %tot avg
 ────────────────────────────────────────────────────────────────────
 ────────────────────────────────────────────────────────────────────

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [October 28, 2022, 2:05pm UTC](https://discourse.julialang.org/t/macro-for-counting-the-number-of-times-a-function-is-called/3129/19 "2022-10-28T14:05:37Z")

</div>

```julia
module MyModule 

using TimerOutputs
const to = TimerOutput()

function myFunc()
    @timeit to "myFunc" begin 
        sleep(0.00001)
    end 
    return 
end

end

using TimerOutputs
TimerOutputs.reset_timer!(MyModule.to)

for i in 1:100
    MyModule.myFunc()
end

show(MyModule.to)

```

Result:

```julia
julia> show(MyModule.to)
 ────────────────────────────────────────────────────────────────────
                            Time Allocations
                   ─────────────────────── ────────────────────────
 Tot / % measured: 686ms / 33.3% 654KiB / 2.3%

 Section ncalls time %tot avg alloc %tot avg
 ────────────────────────────────────────────────────────────────────
 myFunc 100 229ms 100.0% 2.29ms 15.2KiB 100.0% 156B

```
