Yes, they are much better They are allocated on a stack, while mutable structs are allocated in a heap. It means, that all operations like creating/reading are much slower for mutable structures
For example
using BenchmarkTools
using Setfield
mutable struct Foo
a::Int
end
struct Bar
a::Int
end
Creation operation
function f1()
map(i -> Foo(i), 1:10000)
end
function f2()
map(i -> Bar(i), 1:10000)
end
@btime f1();
# 50.576 μs (10002 allocations: 234.45 KiB)
@btime f2();
# 8.269 μs (2 allocations: 78.20 KiB)
Reading operations
function g(v)
res = 0
for el in v
res += el.a
end
res
end
vfoo = f1()
vbar = f2()
@assert g(vfoo) == g(vbar)
@btime g($vfoo)
# 5.394 μs (0 allocations: 0 bytes)
@btime g($vbar)
# 689.520 ns (0 allocations: 0 bytes)
Even updating is faster with immutable structures
function h1!(v)
for el in v
el.a *= 2
end
end
function h2!(v)
for (i, el) in pairs(v)
@set! el.a *= 2
v[i] = el
end
end
@btime h1!(v) setup=(v = deepcopy($vfoo));
# 8.399 μs (0 allocations: 0 bytes)
@btime h2!(v) setup=(v = deepcopy($vbar));
# 5.959 μs (0 allocations: 0 bytes)
It’s a little more complicated to write updating function, but as you can see, it’s worth it.