Allocations reported by `@time`

I am confused by the following results of @time. I understand that the first call contains compilation overhead. But why is the second call allocate much more then the third?

julia> mutable struct M{T}; inner::T; end

julia> function doit1(o, n)
           for i in 1:n
               ret = o.inner
               if i == n
                   return ret
               end
           end
           error()
       end
doit1 (generic function with 1 method)

julia> o = M(1)
M{Int64}(1)

julia> @time doit1(o, 10^1)
  0.016022 seconds (15.82 k allocations: 853.133 KiB)
1

julia> @time doit1(o, 10^5)
  0.004108 seconds (1.93 k allocations: 115.715 KiB)
1

julia> @time doit1(o, 10^5)
  0.000243 seconds (5 allocations: 176 bytes)
1

Maybe you should use

function doit1(o::M{T}, n) where T
...

the results of @time can fluctuate (especially for such a ‘tiny’ function)

consider @btime from the BenchmarkTools.jl package, which should help you with that.

mutable struct M{T}; inner::T; end
function doit1(o, n)
           for i in 1:n
               ret = o.inner
               if i == n
                   return ret
               end
           end
           error()
       end


o=M(1)

@time doit1(o, 10^1)
@time doit1(o, 10^5)

#the results of time fluctuate heavily
for i=1:50
    @time doit1(o, 10^5)
end
#import Pkg
#Pkg.add("BenchmarkTools")
using BenchmarkTools

@btime doit1(o,10_000)
@btime doit1(o,100_000)
#@btime doit1($o,1)
#@btime doit1($o,10_000)

The time yes, but not really the allocations.

julia> @time doit1(o, 10)
  0.006965 seconds (21.90 k allocations: 1.196 MiB)
1

julia> @time 10^5
  0.002142 seconds (1.88 k allocations: 115.072 KiB)
100000

julia> @time doit1(o, 10^5)
  0.000046 seconds (5 allocations: 176 bytes)
1

It seems that the allocations comes from compiling the 10^n function for different literal n.

3 Likes

It seems that the allocations comes from compiling the 10^n function for different literal n .

I did not understand what you said and had already wrote an answer but checked ^ documentation first, and saw:

  ^(x, y)

  Exponentiation operator. If x is a matrix, computes matrix exponentiation.

  If y is an Int literal (e.g. 2 in x^2 or -3 in x^-3), the Julia code x^y is
  transformed by the compiler to Base.literal_pow(^, x, Val(y)), to enable
  compile-time specialization on the value of the exponent. (As a default fallback
  we have Base.literal_pow(^, x, Val(y)) = ^(x,y), where usually ^ == Base.^ unless
  ^ has been defined in the calling namespace.)

Would never have expected this.

1 Like