I'm measuring memory in build. The Unity Objects allocated memory very slowly crawling upwards (350.5 mb, 446.1 mb), but the All of Memory Private part is incredibly huge between the two snapshots.
The memory gain is incredible. 1.5 gb increase.
How to fix this?
#Can someone explain what is happening in the memory and how to fix this?
1 messages · Page 1 of 1 (latest)
You are creating materials and not destroying them. And you probably have similar leaks for other unity objects you create at runtime (meshes, textures, etc.)
where can you see this?
In the first line of your screenshot and by the fact that no project needs 40K+ materials
well, I'm calling Destroy(gameObject)
I don't really know what else should I call
- its just 40 mb
based on the profiler
You need to destroy all unity objects that you instantiate, not just gameobjects. Materials and meshes you create don’t go away when the gameobjects that use them are destroyed
well, we are talking about around 80.000 gameobjects and their components...
it would not be that easy to go through all of their components separately
or you only mean if a unity object was created by the GameObject.Instantiate?
you need to look at your code an see where you create the objects, then add cleanup code there which runs on destroy of the gameobject that created the instances
directly?
well, 11 days ago this was not happening, at least not the Untracked- Private was increasing
and since then I doubt these have been added
you would first check how/where your unaccounted objects are created.
the almost only thing what I did, is that I disabled the object pool (LeanPool)
and I added Destroy(gameObject) instead
where they would have been cached
but with GameObject.Instantiate?
because there are million places which generates unity objects, so I don't know which you mean
@brittle merlin ?
You need to see where these what these leaked materials are referenced by. Surely there's no "million places" that instantiate these objects. It must be whatever was using that LeanPool thing, since a pools is exactly what would prevent an issue like this.
As for the untracked memory it's hard to tell, but on possible explanation is a native plugin that allocates memory.
I disabled the pool, because it created a lot of unnecessary objects as well
and those counts are everywhere in the project
at least in 15-20 different classes
and I don't even know (and don't have time) to figure out the optimal/minimum number those pools should use, because mostly I don't even know what those objects are
"what these leaked materials are referenced by"
I can't understand that window again
I mean I can see where they are
but how to decide which are the intentional good instances and which are the bad ones, which are unnecessary?
yesterday night in the same session I used unload unused assets, and that cleared up half of the material instances
but that didn't clear up much of the Private memory
@brittle merlin
this is why I'm not sure its caused by material count
or 21000 is still too much?
It's kinda a lot. You probably shouldn't have more than you have draw calls(and even than it would be super inefficient), so maybe less than a few thousand. What I think is happening is that your code keeps on doing something like renderer.material in many places, and especially in one time effects or projectiles or stuff like that. Objects that pop in and pop out often. If inside such an object a material is modified, it would create a new copy, but after the object is destroyed, the copy material still remains in memory until scene load.
If that's the case, the ideal way to deal with it, is have the objects pooled, create a new material instance for them on spawn/init, modify that material via a direct reference(not via renderer), and when the object is finally destroyed, destroy the material as well.
Honestly, this shouldn't be your responsibility. It should be of whoever wrote the problematic code. If your task is just to optimize, then you only need to identify issues like that and pass them to whoever fucked up.
No, I don't think this is related to the materials.
@jolly kite so the issue is that the material instances (created with "new Material") should be destroyed with Destroy(materialInstance), right?
Yes. As well as materials accessed with renderer.material.
its a new comparison made from new snapshots (I enabled back the objectpool), so the material counts are better, although Private is still huge, around 1 gb
so I guess the materials named as Instance are all created from code, right?
Yes.
maybe not, but honestly I'm not 100% sure what is the solution, and until then I don't want to give this task to anybody
@jolly kite okay, so it seems its almost impossible to replace renderer.material into renderer.sharedMaterial or MaterialPropertyBlock, because most of these use EnableKeyword and DisableKeyword, which is not available from MaterialPropertyBlock
and I can't decide which should be unique or which is shared
that would take weeks until I would clearly see it
so... should I look for infinitely increasing data structures using Material?
but you also said this... so I'm confused
There are several issues. The material leak, and the untracked memory, which is probably a native plugin or something.
so the untracked memory is not the materials?
You don't have to replace them with shared material, but if you do use .material, you need to keep track of it and dispose it later.
Very unlikely.
even if chatgpt was 100% confident? because it said the NDA platform creates stuff for each material
Platforms themselves don't create anything. It has to be the application. Now, it could be something specific to the platform, but if it's unity allocating it, it should provide info on it.
this is what it said yesterday
While it's possible, the memory for PSOs should still be allocated by unity itself.
okay, what can I do?
I'm fully inexperienced in figuring out what Private is or how to decrease it
That's the thing - no one is.
My guess is that it could be a native plugin, that I've mentioned many times over.
yeah, but what native plugin
That, I can't tell you. I don't know what native plugins you use in the project.
we use like 7-8 or more plugins...
although I don't know what do you mean by plugin
everything is a plugin in Unity
While I'm sceptical about it, it can be PSOs. I guess you can confirm it by disabling the huge amount of materials from spawning and checking if it correlates with decrease of the untracked memory
Not sure what you mean by "everything is a plugin". It's not.
Only plugins are plugins.
even commenting out these lines takes long, because there are 200+ occurences of renderer.material all over
but I'm checking it
the reason why I think its not a dll, because Untracked - Private grew constantly, and it grew more quickly when I disabled object pool (and I destroyed everything on their end of their lifetime) instead of caching.
When I enabled it back, it grew much slower. But still grew a lot
with pool - 0.73 gb Private increase after 50 min gameplay in the same scene
without pool - 1.41 gb Private increase after 20 min gameplay in the same scene
I see. Then it might indeed be something related to the graphics api.
I don't understand the whole thing again...
left is "before", right is "after" I commented out the renderer.material and new Material assignments. I made these measurements from NDA build, and I stashed the material commented out lines to get the left image.
and still.... if I place breakpoints near the commented out lines, these are not even gets called at all..... then how could it solve anything...
I mean, even if some of it was related to materials, there's no guarantee that all of it is.
Untracked memory could be anything.
it should be btw
okay, since then I could fix my VS issue, because even that can't work properly with too much breakpoints
so when I tried to use it with less, it stopped in near the commented out lines
so yeah
that's the issue
Material[] mats = rend.materials;
lines like this
its a guarantee, because I shelved only those changes
I don't have time to explain, but will write more about it later
@jolly kite
5.28 gb -> 6.10 gb (original)
5.21 gb -> 5.72 gb (optimized)
5.28 gb -> 5.53 gb (material assignments and readings disabled)
its the same amount period measurement, every game related setting is the same
and its only the renderer.material things
Is that the untracked memory thing?
I mean these values I wrote now is all of memory, but this is how material assignments and readings modify memory
on the NDA platform
The managed memory yeah. But does it actually reduce the untracked memory too?