Striking performance difference between MeshFilter.material and MeshFilter.materials

Guys,
I feel it’s a point to take a look at URP, looks like there’s no reason it should be that different, so I am sharing in case someone knows a reason for it or if Unity Team wants to take a look.
I am getting a gigantic performance difference between the properties material and materials:

material takes some nanoseconds
this.MeshRenderer.material = tileDefinition.material;

materials is taking hundred times more and showing thousand GC.Alloc instances on profiler
var materials = this.MeshRenderer.materials;
materials[0] = material1;
materials[1] = material2;
this.MeshRenderer.materials = materials;

On this picture I called this 4 lines of materials around 15-20 times and got 4.32ms for this, while using material to the same objects It does not even appear on my profile, It’s a gigantic difference.
6382593--711267--upload_2020-10-5_8-59-29.png

Profiling with StopWatch to get how many ticks elapsed:
ElapsedTicks Single Material: 9
ElapsedTicks Materials: 537 (50 times higher cost)

My Unity version:
6382593--711261--upload_2020-10-5_8-56-32.png

6382593--711261--upload_2020-10-5_8-56-32.png

When you access Renderer.materials Unity creates a copy of the array to return, which allocates garbage as you see. This is true for all Unity getters and methods which return arrays.

Worse yet: when you read the materials array for the first time, Unity creates copies of the materials in the sharedMaterials array, so you can change their properties without affecting other meshes using the same materials. Unity does not destroys those materials, they will remain in memory until you either manually destroy them, load a non-additive scene, or call unloadUnusedResources.

Oh right, now it makes sense for me, thanks for you explanation, I see I will have to work around using Atlas or something like that… :face_with_spiral_eyes:

Oh, I solved doing this based on Kokkubhub observation, do not use the property getter and no more GC.Allocs

private static Material[ ] bufferMaterials2 = new Material[2];

bufferMaterials2[0] = material1;
bufferMaterials2[1] = material2;
this.MeshRenderer.materials = bufferMaterials2;