Abstract type

Avoid containers with abstract type parameters

a = Real[]

push!(a, 1); push!(a, 2.0); push!(a, π)
3-element Vector{Real}:
 1
 2.0
 π = 3.1415926535897...

Since Real objects can be of arbitrary size and structure, a must be represented as an array of pointers to individually allocated Real objects. With concrete type Float64, b is stored as a contiguous block of 64-bit floating-point values that can be manipulated efficiently.

b = Float64[]

push!(b, 1); push!(b, 2.0); push!(b,  π)
3-element Vector{Float64}:
 1.0
 2.0
 3.141592653589793

Avoid struct fields with abstract type

Types matter, when you know anything about the types of your variables, include them in your code to make it run faster

struct Cube
    length
    width
    height
end

struct CubeTyped
    length::Float64
    width::Float64
    height::Float64
end

struct CubeParametricTyped{T <: Real}
    length::T
    width::T
    height::T
end

volume(c) = c.length*c.width*c.height

c1 = Cube(1.1,1.2,1.3)
c2 = CubeTyped(1.1,1.2,1.3)
c3 = CubeParametricTyped(1.1,1.2,1.3)
@show volume(c1) == volume(c2) == volume(c3)
volume(c1) == volume(c2) == volume(c3) = true
true
using BenchmarkTools
@btime volume($c1) # not typed
@btime volume($c2) # typed float
@btime volume($c3) # typed parametric
  18.942 ns (1 allocation: 16 bytes)
  2.775 ns (0 allocations: 0 bytes)
  2.785 ns (0 allocations: 0 bytes)
1.7160000000000002

@code_warntype volume(c1)
MethodInstance for volume(::Cube)
  from volume(c) @ Main In[5]:1
Arguments
  #self#::Core.Const(volume)
  c::Cube
Body::Any
1 ─ %1 = Base.getproperty(c, :length)::Any
│   %2 = Base.getproperty(c, :width)::Any
│   %3 = Base.getproperty(c, :height)::Any
│   %4 = (%1 * %2 * %3)::Any
└──      return %4

@code_warntype volume(c2)
MethodInstance for volume(::CubeTyped)
  from volume(c) @ Main In[5]:1
Arguments
  #self#::Core.Const(volume)
  c::CubeTyped
Body::Float64
1 ─ %1 = Base.getproperty(c, :length)::Float64
│   %2 = Base.getproperty(c, :width)::Float64
│   %3 = Base.getproperty(c, :height)::Float64
│   %4 = (%1 * %2 * %3)::Float64
└──      return %4

@code_warntype volume(c3)
MethodInstance for volume(::CubeParametricTyped{Float64})
  from volume(c) @ Main In[5]:1
Arguments
  #self#::Core.Const(volume)
  c::CubeParametricTyped{Float64}
Body::Float64
1 ─ %1 = Base.getproperty(c, :length)::Float64
│   %2 = Base.getproperty(c, :width)::Float64
│   %3 = Base.getproperty(c, :height)::Float64
│   %4 = (%1 * %2 * %3)::Float64
└──      return %4