# How much memory does a reference to a class take?

Let’s say I have a class:

``````public class _Container{

public byte Item;

}

public Container _C = new Container();
``````

Now this class takes 8bits of memory. But what happens if I add references to that class?

``````public Container _D = _C;
public Container _E = _C;
public Container _F = _C;
public Container _G = _C;
....
``````

How much memory does each reference take? Since in theory there is only 1 class initialized

Assuming 64-bit, every reference is 8 bytes (a pointer).

Instance size is a bit more complicated, afaik it’s: 12 bytes overhead + the sum of all the fields on it (and possibly padding between them for alignment), then the whole thing is padded to a multiple of 8 bytes. So the Container class you gave with 1 byte storage is 16 bytes (12 + 1 = 13, padded to 16)

1 Like

So let me see if I understand, the class is 16 bytes?

``````    public Container _D = _C;
public Container _E = _C;
public Container _F = _C;
public Container _G = _C;
``````

You say each reference is 8 bytes so does this take 8x4 = 32 bytes of memory?

is it bytes or bits btw? seems an extreme amount

What year do you live in?
On 64-bit platforms pointers are 8 bytes (64 bits). With 8-bit references your entire game would be limited to 256 objects (in total for all types of objects!).
A reference to an object not guaranteed to be limited to just 8 bytes, it might be pointing to some additional resource to enable moving garbage collector.

With even low end devices like phones having at least hundreds of megabytes of memory available, references to objects is not where the memory is wasted.

1 Like

Bytes. Pointers add up. The difference gets even bigger if you compare an array of objects to an array of structs:

struct SomeThing { public byte a; } ← this is 1 byte (may also add in padding dependent on the runtime though, but afaik not normally done)
Something[ ] array = new Something[1024] ← this is 1024 bytes with afaik about 24 bytes overhead

class Something { public byte a; } ← this is a 16-byte instance
Something[ ] array = new Something[1024] ← this is 8 * 1024 = 8192 bytes plus 24 bytes overhead
Then somewhere else you have created 1024 instances of Something, 16 bytes each → 16384 bytes
so a total of 24624 bytes of memory to store 1024 bytes of data

If it’s just a thousand things - you probably shouldn’t care. If it’s 4 references - definitely don’t care.
But if you start having (tens of) millions of things it can start making a big difference.

As far as I’m aware this is one of the biggest issues with Java for game dev, it doesn’t support proper “struct” types (yet, I think they’re adding it around now)

=D I see

Thanks for the extra info about struct and class! That’s why I was asking this question, I’ll tread lightly around it

1 Like

I have another question that I was wondering if someone could answer please:

If I have a bunch of cloned simple objects and one manager object,

the manager object has many variables in it like so:

``````public class managerscript{
public int worldsize_x;
public int worldsize_y;
public int worldsize_z;
}
``````

and the simple object just has:

``````public managerscript mngr;
``````

does this reference to the manager script count as one reference or is it multiplied by however many variables are in the manager script?

In other words when I call from the single object:

``````x = mngr.worldsize_x
``````

am I making some sort of shortcut through references or is declaring a reference to the manager in the simple object essentially invisibly creating these extra references:

``````public managerscript mngr;

//vv are these created automatically in the background?

mngr.worldsize_x;
mngr.worldsize_y;
mngr.worldsize_z;
``````

so each simple object I cloned would have a ton of useless references piling up

If this is a confusing question please let me know so I can try to explain better

public managerscript mngr;

this stores a pointer inside the simpleobject class, which points to some location holding a managerscript (or null)

the storage requirement for the pointer is multiplied by however many simpleobjects you spawn
the storage requirement for the actual managerscript is multiplied by however many managerscripts you spawn (probably one)

x = mngr.worldsize_x

this looks up the location that mngr is pointing to, and reads “worldsize_x” from that object. the read value is than copied into x.
If x is defined in a method like void DoSomething() { int x = mngr.worldsize_x; } then it is only a temporary thing that exists while the function is running, taking no memory use.
If x is defined in the class like class simpleobject { int x; void Do () { x = mngr.worldsize_x; } } then it is storage-per-simpleobject that you’re copying data into.
In both cases you’re not making extra references

Ok thanks! I asked this question because i was profiling memory in my project and there were some textures that were showing 100 references in the scene where there should only be 1, and the profiler was pointing me to my cloned objects as containing references of that texture. However in my cloned objects the only reference I have is to my manager (which does have those textures but it is the only object that has them), so I was wondering if the reference to the manager in the cloned objects was creating references to everything in the manager.

Is that normal or I might have some leak in my scripts?

a reference isn’t the same as an instance

the references in the memory profiler are like “these objects (in)directly have pointers to this texture, so we keep the texture alive”

1 Like

Ahhh ok thanks a lot for the help! =D

This is only true for versions before 2019.3, we fixed it to only report direct references in that version.

1 Like

Thanks, I have 2019.2

Well, theoretically not, unless it has static memory to it and has been statically initialized, which can happen because something in the code is doing something with the type, e.g. calling a static method on it.

Also the Mono/IL2CPP scripting Virtual Machines used in Unity have to store the Type Metadata in memory. That memory is lazily initialized though so similar to the static memory, it would only be loaded into VM memory because the Type is used or because the Memory Profiler had to trigger the initialization/inflation of the type on capture… The later would e.g. happen if you have an array of your type or some generics referring to the type but never actually use the type directly. It would therefore not be initialized when the capture is made and the Profiler would show you that memory as and just give you a blank stare if you ask what type that was supposed to be. Earlier Unity versions had that problem so now, capture force initializes all Types that are refered to on the heap, even if their actual type info wasn’t needed yet (e.g. because nothing called any functions on it).

No, we already covered that point above, that’d be some 12 Bytes Object header memory, on 64 bit builds 8 bytes for any reference to it, and a GCHandle of 8 bytes (iirc) for the instance (at least one, unless you take out different GCHandles on the same object, e.g. pinning it).

Anyways, there is arguing the theoretically, and then there is the option to just take a memory snapshot and check out what the memory usage in of these objects actually looks like by checking it out in the Memory Profiler package. You can see all fields and sizes of each managed object and each Type and their statics in there (granted, not yet entirely intuitive to find these). Consts are a bit of a tricky thing as they are part of the DLL though. Also, no way to see how much each type takes up in VM Memory yet either… We’ll get there eventually…

I have a question though. Multiple references are talked about, but not multiple instances with few references.
If I Instantiate a vanilla class in Update loop. (Every frame instantiate a new class and assign it to the same reference)

``````//inside Update
localfield = new Vinilla()
``````

The reference stays at one, but the instance could be more and more as the game goes on. Does this lead to RAM or finally CPU overhead?
I know GC would take care of objects that’s not referenced to, but it still takes CPU to handle it, right?

Yes garbage collection takes CPU cycles which is why it is often avoided like the plague to create unnecessary garbage in Unity. The discarded instances will continue to take up memory until they are garbage collected, at which point CPU cycles will need to be expended to clean them up. Much better to simply reuse your single instance rather than create a new one each frame.