3

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++;
}

Shogunivar
  • 1,237
  • 11
  • 18
Dave502619
  • 57
  • 6
  • How are you benchmarking / profiling the code, and are you 100% sure it is *this loop alone* which takes 250ms? – meowgoesthedog Aug 15 '18 at 09:10
  • i'm using a simple stopwatch class and starting/stopping around the loop code. There is really nothing else running as is a simple implementation of allocating particles to vertices. I get/set the particles either side of the loop as Unity requires but i've used that technique before with no issues. – Dave502619 Aug 15 '18 at 09:17

4 Answers4

2

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++ ];
    }
}
Milan Egon Votrubec
  • 3,696
  • 2
  • 10
  • 24
1

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.

Serkan Pekçetin
  • 658
  • 7
  • 14
0

The loop is not running slow; It's 250ms for this loop, Unity Engine and any other assets that you may or may not have.

Ido H Levi
  • 181
  • 9
  • ok so is there another way to implement this to acheive the same result that would run faster? – Dave502619 Aug 15 '18 at 09:05
  • Unfortunately no, but if you want your game/app to run faster, try to optimize the assets you use and using optimization techniques such as LOD, etc. – Ido H Levi Aug 15 '18 at 09:08
  • Ok thanks - i am going to split over a number of frames to lessen the impact on the frame. Now that i know that my code is correct. – Dave502619 Aug 15 '18 at 09:13
-1

I have had this issue as well. If possible you should pre-generate an array of the vertices in the order that the triangle array specifies them. Otherwise you are accessing random places in memory, which really destroys performance.

Jkratz
  • 1