Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Striking performance difference between MeshFilter.material and MeshFilter.materials

Discussion in 'Universal Render Pipeline' started by dukenukem4d, Oct 5, 2020.

  1. dukenukem4d

    dukenukem4d

    Joined:
    Jul 30, 2019
    Posts:
    14
    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.
    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:
    upload_2020-10-5_8-56-35.png
     

    Attached Files:

  2. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,750
    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.
     
  3. dukenukem4d

    dukenukem4d

    Joined:
    Jul 30, 2019
    Posts:
    14
    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... :confused:
     
  4. dukenukem4d

    dukenukem4d

    Joined:
    Jul 30, 2019
    Posts:
    14
    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;
     
    Last edited: Oct 5, 2020