# How to avoid vectors of abstract types?

**URL:** <https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132>\
**Category:** Performance\
**Tags:** question\
**Created:** [June 2, 2022, 1:17pm UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132 "2022-06-02T13:17:09Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![BatyLeo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/batyleo/32/35017_2.png) [@BatyLeo](https://discourse.julialang.org/u/BatyLeo)\
**Post date:** [June 2, 2022, 1:17pm UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/1 "2022-06-02T13:17:09Z")

</div>

Hello,

I started using Julia intensively a few months ago, and I keep coming across situations where I have vectors of abstract types, which [should be avoided](https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-abstract-container) for performance reasons. I can’t seem to find satisfying solutions to these situations.

Here is a simplified example of the last time I had this problem:

I’m doing some machine learning experiments, during which I log several metrics, which number and type can differ between experiments. For this, I define an `AbstractMetric` abstract type, and, for each metric, one concrete type I can dispatch on. For example:

```julia
# Abstract type
abstract type AbstractMetric end

function log!(m::AbstractMetric; kwargs...)
    push!(m.history, m(kwargs...))
end

```

```julia
# Loss concrete types
struct Loss <: AbstractMetric
    history::Vector{Float64}
end

Loss() = Loss(Float64[])

function (m::Loss)(; loss, groundtruths, predictions, kwargs...)
    return sum(loss(y, y_pred) for (y, y_pred) in zip(groundtruths, predictions))
end

# Accuracy concrete type
struct Accuracy <: AbstractMetric
    history::Vector{Float64}
end

Accuracy() = Loss(Float64[])

function (m::Accuracy)(; groundtruths, predictions, kwargs...)
    return mean(y == y_pred for (y, y_pred) in zip(groundtruths, predictions))
end

# Other metrics
...

```

I store all the current metrics in a vector and use a for loop calling the `log!` method.

Problem: the vector is a `Vector{AbstractMetric}`.  
Is there a better implementation that can avoid that ?

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [June 2, 2022, 1:43pm UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/2 "2022-06-02T13:43:12Z")

</div>

if the length is expected to be small, use a Tuple

---

<div class="post-metadata">

**Author:** ![brenhinkeller](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brenhinkeller/32/36648_2.png) [@brenhinkeller](https://discourse.julialang.org/u/brenhinkeller)\
**Post date:** [June 2, 2022, 1:44pm UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/3 "2022-06-02T13:44:47Z")

</div>

Yeah, there are a lot of performance problems that could be avoided if people used tuples instead of arrays and namedtuples instead of dicts for small arrays and dicts…

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [June 2, 2022, 2:12pm UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/4 "2022-06-02T14:12:57Z")

</div>

Have you actually determined that this is an issue, by profiling? If not, then unless one iteration of your training loop is extremely fast then I doubt the overhead from dynamic dispatch is adding much.

---

<div class="post-metadata">

**Author:** ![BatyLeo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/batyleo/32/35017_2.png) [@BatyLeo](https://discourse.julialang.org/u/BatyLeo)\
**Post date:** [June 3, 2022, 7:41am UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/5 "2022-06-03T07:41:37Z")

</div>

> [@jling](#):
>
> if the length is expected to be small, use a Tuple

Thank you !  
Tuple seems the way to go here, didn’t think of that.

---

<div class="post-metadata">

**Author:** ![BatyLeo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/batyleo/32/35017_2.png) [@BatyLeo](https://discourse.julialang.org/u/BatyLeo)\
**Post date:** [June 3, 2022, 7:47am UTC](https://discourse.julialang.org/t/how-to-avoid-vectors-of-abstract-types/82132/6 "2022-06-03T07:47:18Z")

</div>

> [@cjdoris](#):
>
> Have you actually determined that this is an issue, by profiling? If not, then unless one iteration of your training loop is extremely fast then I doubt the overhead from dynamic dispatch is adding much.

I’m not sure this in particular is an issue, but profiling shows that metrics computation currently take about 70% of the training loop time. That’s why I’m trying to solve potential performance issues.
