Thank you for everyone's comments.
To summarize, the slow version needs to perform memory allocation to 
protect itself against potential type instability should future types and 
associated evaluate function be defined, whereas the 'fast' version is 
protected from this and the compiler can optimize it.

Also, I learned about code_warntype and code_llvm.

On Friday, April 1, 2016 at 6:56:52 PM UTC-7, Tim Wheeler wrote:
>
> Hello Julia Users.
>
> I ran into a weird slowdown issue and reproduced a minimal working 
> example. Maybe someone can help shed some light.
>
> abstract Feature
>
> type A <: Feature end
> evaluate(f::A) = 1.0
>
> type B <: Feature end
> evaluate(f::B) = 0.0
>
> function slow(features::Vector{Feature})
>     retval = 0.0
>     for i in 1 : length(features)
>         retval += evaluate(features[i])
>     end
>     retval
> end
>
> function fast(features::Vector{Feature})
>     retval = 0.0
>     for i in 1 : length(features)
>         if isa(features[i], A)
>             retval += evaluate(features[i]::A)
>         else
>             retval += evaluate(features[i]::B)
>         end
>     end
>     retval
> end
>
> using ProfileView
>
> features = Feature[]
> for i in 1 : 10000
>     push!(features, A())
> end
>
> slow(features)
> @time slow(features)
> fast(features)
> @time fast(features)
>
> The output is:
>
> 0.000136 seconds (10.15 k allocations: 166.417 KB)
> 0.000012 seconds (5 allocations: 176 bytes)
>
>
> This is a HUGE difference! Am I missing something big? Is there a good way to 
> inspect code to figure out where I am going wrong?
>
>
> Thank you in advance for any guidance.
>
>
> -Tim
>
>
>
>
>
>

Reply via email to