Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing mesh vertices performance issue

I am having trouble with this code running slow (around 250ms to execute the loop)

The mesh.triangles.Length is 8700.

I am using c# on the latest Unity platform (version 2018.2.3).

I suspect this is because I am switching between two arrays for each iteration, ie. i take a value from triangle then look up the vertices element of it.

mesh.triangles is an array of integers. mesh.vertices is an array of Vector3's.


while (j < mesh.triangles.Length)  
{

    m_Particles [currentParticlePos].position =  vertices[mesh.triangles[j]];   

    // allocate a particle to every 3rd vertex position.
    j = j + 3;
    currentParticlePos++;
}

like image 957
Dave502619 Avatar asked Aug 08 '26 02:08

Dave502619


2 Answers

Manually forcing some micro-optimisations here MIGHT help you out.

Firstly, mesh.triangles is a property, with its own getter and setter. You're going to get a slight performance hit there every loop. So let's store that address as a local variable before the loop even starts.

Secondly, the value of mesh.triangles.Length is always the same. So let's store that in a local variable, instead of calling the property every loop.

Following on from that, your code uses vertices [ ] while your question refers to mesh.vertices [ ]. If you're checking mesh.vertices [ ] every loops, you'll want to locally store that as well.

Now, depending on the compiler, the following micro-optimisations may already have been taken care of. So, you'll have to use your timing technique to verify if this was worthwhile. Having said that, let's now look at the code:

int [ ] triangles = mesh.triangles;
int length= triangles.Length;
int [ ] vertices = mesh.vertices;

while (j < length)  
{
  m_Particles [ currentParticlePos++ ].position = vertices [ triangles [ j ] ];   
  // allocate a particle to every 3rd vertex position.
  j = j + 3;
}

As a side note, and while it doesn't help you right now, C#7.x introduces ref struct and a few other helpful features that'll speed up access, keeping everything on the stack. This article is an interesting read and will be useful when Unity catches up.

Edit : If your mesh doesn't change (which is probably likely), you could then predefine an array of the exact vertices you need. You also then just have to increment a single variable. This is an extreme micro-optimisation. This might help with CPU pre-fetching... (insert shrugging emoji here).

// The mesh. Assigned as you see fit.
Mesh mesh;

// The length of the new vertices array, holding every third vertex of a triangle.
int length = 0; 

// The new vertices array holding every third vertex.
Vector3 [ ] vertices;

void Start ( )
{
    int [ ] triangles = mesh.triangles;
    length = triangles.Length / 3;
    vertices = new Vector3 [ length ];

    for ( int count = 0; count < length; count++ )
        vertices [ count ] = mesh.vertices [ triangles [ count * 3 ] ] ;
}

private void Update ( )
{
    int j = 0;
    while ( j < length )
    {
        m_Particles [ j ].position = vertices [ j++ ];
    }
}
like image 195
Milan Egon Votrubec Avatar answered Aug 09 '26 16:08

Milan Egon Votrubec


You are using mesh but you are not modifying any values. In such cases, you might consider using sharedMesh instead. The problem with mesh in your particular case is that, mesh creates a duplicate and returns it. With sharedMesh you are free from the extra overhead of another instance of your mesh. Have a look at the documentation of mesh and sharedMesh for further information.

like image 24
Serkan Pekçetin Avatar answered Aug 09 '26 17:08

Serkan Pekçetin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!