# Memory and composition

**URL:** <https://discourse.julialang.org/t/memory-and-composition/4633>\
**Category:** General Usage\
**Tags:** question\
**Created:** [July 4, 2017, 8:58am UTC](https://discourse.julialang.org/t/memory-and-composition/4633 "2017-07-04T08:58:53Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 4, 2017, 8:58am UTC](https://discourse.julialang.org/t/memory-and-composition/4633/1 "2017-07-04T08:58:53Z")

</div>

If I have a `struct` that has another `struct` as a field, is the latter always copied as a whole? Eg

```julia
struct Large
    a::Int
    b::Int
    c::Int
end

struct UsesLarge
    l::Large
    d::Int
end

l = Large(1,2,3)
sizeof(l) # 24

u1 = UsesLarge(l, 4)
sizeof(u1) # 32

```

I am asking because for a problem I am working on, several small objects `y` only make sense in context of a larger one `X`. Currently the calling convention of my functions is `dostuff(X, y)` but it would be very natural to compose the `X` into the `y`s. However, I am worried about memory, because there are many `y`s and `X` is large.

I don’t know how to reason about size in this case. Can I keep my objects immutable (`struct`) and yet share memory for the `X`s? Is there any way to ensure this? I found [this in the devdocs](https://docs.julialang.org/en/stable/devdocs/object/) but I don’t know enough to understand it.

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [July 4, 2017, 10:06am UTC](https://discourse.julialang.org/t/memory-and-composition/4633/2 "2017-07-04T10:06:23Z")

</div>

Make your X into a mutable struct, this way it is copied by reference and not value.

your y’s will still be structs, that is:

1. copied by value
2. efficiently passed into a function
3. eliminating several indirections when accessing fields , due to compiler optimizations.

```julia
type Large
    a::Int
    b::Int
    c::Int
end

immutable UsesLarge
    l::Large
    d::Int
end

L = Large(1,2,3)
y1 = UsesLarge(L,10)
y2 = UsesLarge(L,20)

y1.l.a = 100
y2.l.a == 100 #true

```

I am still on 0.5 waiting for some packages to update to 0.6, hence the `type` and `immutable`  
and not `struct`

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 4, 2017, 2:40pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/3 "2017-07-04T14:40:59Z")

</div>

Thanks, but this is more of a workaround ­— I like to mean what I say when coding.

Also, it is unclear to me if `struct` of `struct`s would always be unshared, or just sometimes, up to the discretion of the compiler. I found  
[https://groups.google.com/forum/#!topic/julia-users/ZPSiiK4b1T0](https://groups.google.com/forum/#!topic/julia-users/ZPSiiK4b1T0)  
and from way back

> **[Efficient Aggregates in Julia](https://julialang.org/blog/2013/03/efficient-aggregates/)**
>
> Efficient Aggregates in Julia | We recently introduced an exciting feature that has been in planning for some...

where for aggregates, this is discussed as a feature. Maybe I am trying to accomplish something silly, but sometimes I want to opposite.

---

<div class="post-metadata">

**Author:** ![Evizero](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/evizero/32/10118_2.png) [@Evizero](https://discourse.julialang.org/u/Evizero)\
**Post date:** [July 4, 2017, 3:02pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/4 "2017-07-04T15:02:17Z")

</div>

one way to achieve this is by telling `UsesLarge` that `l` should be a reference. You can do this by not typing it concretely. For example just change the following but leave everything else the same

```julia
struct Large{T}
    a::T
    b::T
    c::T
end

```

Now `Large` (as in `l::Large`) is not a concrete type anymore

```julia
julia> sizeof(u1) 
16

```

> [@Tamas\_Papp](#):
>
> Also, it is unclear to me if struct of structs would always be unshared

As I understand it this depends on being a `struct` as well concretely typed. Both must be true.

EDIT: though I am not sure if this actually fixed the thing you are interested in (i.e. not copying all the time). I suspect all this does is avoid the symptom

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [July 4, 2017, 3:07pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/5 "2017-07-04T15:07:49Z")

</div>

This is not a workaround, moreover it is not something new or innovative to Julia.

in C a `struct` is just as in Julia, passed by value.  
a pointer to `struct` is just as a `mutable struct` in Julia, the pointer itself is passed by value  
which means the struct which it points to is “passed by reference”  
because two copies of the same pointer point to the same struct.

In C there is special notation for accessing fields whether its a struct or a pointer to a struct, in Julia this is  
hidden from you, along with the overhead of keeping track of references and cleaning unused mutable structs  
(structs that no pointer references hence are un-acceesible)

in 0.6 lingo  
A `struct` of anything is passed by value, copies are made, it is “unshared”  
A `mutable struct` is passed by reference , a copy of only the pointer(address) is made, it is shared

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 4, 2017, 3:16pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/6 "2017-07-04T15:16:09Z")

</div>

> [@TsurHerman](#):
>
> A struct of anything is passed by value, copies are made, it is “unshared”

Not really. It is always semantically shared, just that it’s not mutable. It is not copied when passing around, only copied when assigned to external slots as a requirement of the ABI.

---

<div class="post-metadata">

**Author:** ![jtravs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jtravs/32/2010_2.png) [@jtravs](https://discourse.julialang.org/u/jtravs)\
**Post date:** [July 4, 2017, 3:19pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/7 "2017-07-04T15:19:04Z")

</div>

Why not use a `Ref{T}`:

```julia
struct UsesLarge
    l::Ref{Large}
    d::Int
end

l = Large(1,2,3)
u1 = UsesLarge(Ref{Large}(l), 4)
sizeof(u1) #16

```

---

<div class="post-metadata">

**Author:** ![jtravs](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jtravs/32/2010_2.png) [@jtravs](https://discourse.julialang.org/u/jtravs)\
**Post date:** [July 4, 2017, 3:20pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/8 "2017-07-04T15:20:14Z")

</div>

And add a constructor

```julia
function UsesLarge(l::Large, d::Int)
    UsesLarge(Ref{large}(l), d)
end

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 4, 2017, 3:32pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/9 "2017-07-04T15:32:07Z")

</div>

Thanks. I have always thought of `Ref` as part of the FFI, but this looks like a workaround. However, I then have to extract the `l` from the `RefValue`.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 4, 2017, 3:33pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/10 "2017-07-04T15:33:55Z")

</div>

Is there a way to compose yet share structure somehow, for one (immutable) `struct`s containing another in `v0.6`? Or should I use `Ref` as suggested by @jtravs?

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [July 4, 2017, 4:21pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/11 "2017-07-04T16:21:40Z")

</div>

> [@yuyichao](#):
>
> Not really. It is always semantically shared, just that it’s not mutable. It is not copied when passing around, only copied when assigned to external slots as a requirement of the ABI.

I see your point, but that is just an optimzation you can guarantee because you demand immutability.

if like in C you could mutate structs and moreover have more than one thread running, you would have to copy  
whenever passing it around.

Anyway objects containing large data like vector and arrays are usually mutable structs.

EDIT:  
@yuyichao  
Why in the following example using unsafe code , I can mutate an immutable in its scope, but not when  
I am trying to get a pointer to it inside a function?

```julia
immutable Large
    a::Int64
    b::Int64
    c::Int64
end

L = Large(1,2,3)
ptr_x = Ptr{Int64}(pointer_from_objref(L))
unsafe_store!(ptr_x,100)
L.a # prints 100 I mutated an immutable

f(x) = begin
    ptr_x = Ptr{Int64}(pointer_from_objref(x))
    unsafe_store!(ptr_x,-100)
end
f(L)
L.a #still 100 although according to what is said here should have been -100

```

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 4, 2017, 5:10pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/12 "2017-07-04T17:10:49Z")

</div>

You are violating the semantics of the language so anything can happen,

---

<div class="post-metadata">

**Author:** ![TsurHerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tsurherman/32/1234_2.png) [@TsurHerman](https://discourse.julialang.org/u/TsurHerman)\
**Post date:** [July 4, 2017, 5:29pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/13 "2017-07-04T17:29:37Z")

</div>

> [@yuyichao](#):
>
> You are violating the semantics of the language so anything can happen

thats a bit harsh 🙂 , I am trying to work with the language using the language.  
Anyway if we remove the meddling `unsafe_store!` we still see the pointers are different.

How can you prove your statement:

> [@yuyichao](#):
>
> It is not copied when passing around

Beside the usual inlining optimizations llvm does ?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 4, 2017, 7:32pm UTC](https://discourse.julialang.org/t/memory-and-composition/4633/14 "2017-07-04T19:32:18Z")

</div>

> [@TsurHerman](#):
>
> thats a bit harsh 🙂

… It’s a bit hard to find a way that’s not… Maybe I’ll just go with the traditional saying: it can [“make demons fly out of your nose”](https://en.wikipedia.org/wiki/Undefined_behavior)…

> [@TsurHerman](#):
>
> the pointers are different.

That pointer is invalid on construction and is insignificant.

> [@TsurHerman](#):
>
> inlining optimizations llvm does

We don’t do any of them. We do pass it as pointer between functions when it’s too big though.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 5, 2017, 5:16am UTC](https://discourse.julialang.org/t/memory-and-composition/4633/15 "2017-07-05T05:16:02Z")

</div>

While demons are interesting, replies to the original question would stil be appreciated.

Am I doing something un-idiomatic, composing a value into multiple instances? Is there anything better than `Ref` for this? Even a definitive statement that there isn’t would help.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [July 5, 2017, 10:43am UTC](https://discourse.julialang.org/t/memory-and-composition/4633/16 "2017-07-05T10:43:14Z")

</div>

> [@yuyichao](#):
>
> We do pass it as pointer between functions when it’s too big though.

Am I seeing something like that in action in this MWE?

```julia
using StaticArrays # just to gobble memory

struct Large{N, T}
    X::StaticVector{N, T}
end

struct Small{N, T}
    y::Float64
    X::Large{N, T}
end

X = Large(@SVector rand(1000)) # abusing StaticArrays
sizeof(X) # 8
sizeof(X.X) # 8000
ys = [Small(randn(), X) for _ in 1:500]
sizeof(ys) # 500*8 = 4000, where is X?

```

Where can I learn more about this?

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [July 5, 2017, 11:01am UTC](https://discourse.julialang.org/t/memory-and-composition/4633/17 "2017-07-05T11:01:35Z")

</div>

> [@Tamas\_Papp](#):
>
> Am I seeing something like that in action in this MWE?

No It’s not something you can observe at this level. The object layout is well defined. Pointerfree leaf immutable types are inlined, anything else aren’t. You are just observing an non-leaf type.
