On Fri, Apr 1, 2016 at 9:56 PM, Tim Wheeler <timwheeleronl...@gmail.com> 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?

This is because of type instability as you will find in the performance tips.
Note that slow and fast are not equivalent since the fast version only
accept `A` or `B` but the slow version accepts any subtype of feature
that you may ever define. Therefore there's no way the compiler can
rewrite the slow version to the fast version.
There are optimizations that can be applied to bring down the gap but
there'll always be a large difference between the two.

>
>
> Thank you in advance for any guidance.
>
>
> -Tim
>
>
>
>
>

Reply via email to