why did this code speed up my GL calls?

I have a custom OnRenderObject() function that draws wireframe meshes using GL_LINES. After adding bunch of objects to the scene I found that rendering about 10-15k triangles will drop my FPS to 9-10. Finally I managed to find the culprit, below is ‘before’ and ‘after’ code.

before:

		Vector3 A, B, C;
		A = B = C = Vector3.zero;
		GL.PushMatrix ();
		GL.MultMatrix (transform.localToWorldMatrix);
		GL.Begin (GL.LINES);
		GL.Color (Color.white);
		for (int fi = 0; fi < currentMesh.triangles.Length; fi += 3) {
			byte fi0 = edgeVisibility [fi];
			byte fi1 = edgeVisibility [fi+1];
			byte fi2 = edgeVisibility [fi+2];
			if (fi0 + fi1 + fi2 == 0) continue;

			A = currentMesh.vertices [currentMesh.triangles [fi + 0]]; // org A
			B = currentMesh.vertices [currentMesh.triangles [fi + 1]]; // org C
			C = currentMesh.vertices [currentMesh.triangles [fi + 2]]; // org B

after:

		Vector3 A, B, C;
		A = B = C = Vector3.zero;
		Vector3[] vertices = currentMesh.vertices;
		int[] triangles = currentMesh.triangles;

		GL.PushMatrix ();
		GL.MultMatrix (transform.localToWorldMatrix);
		GL.Begin (GL.LINES);
		GL.Color (Color.white);
		for (int fi = 0; fi < triangles.Length; fi += 3) {
			byte fi0 = edgeVisibility [fi];
			byte fi1 = edgeVisibility [fi+1];
			byte fi2 = edgeVisibility [fi+2];
			if (fi0 + fi1 + fi2 == 0) continue;

			A = vertices [triangles [fi + 0]]; // org A
			B = vertices [triangles [fi + 1]]; // org C
			C = vertices [triangles [fi + 2]]; // org B

So why does the second version work significantly faster?
Shouldn’t accessing properties in a loop be optimized by the compiler?

Mesh.vertices is a property, not a field. The actual mesh data is not stored on the managed side but on the native C++ side. Whenever you “read” that property you actually create a new managed array which is filled with the vertex information. That means in your original code you create 4 arrays each iteration. So if you have 10k vertices, a single array has a size of 4310k bytes == 120kb. Since your loop has 10k iterations you create this array 40000 times.

And no, accessing properties can’t be optimised by the compiler since properties are just syntactic sugar for a method call. A method can have sideeffects which the compiler can’t predict. Simple properties like

private int m_Something;
public int Something
{
   get { return m_Something;}
}

could be inlined by the JIT compiler at runtime, however as i said the vertices array actually calls a native method.

So your “optimised” version will only create 1 of those 120kb arrays instead of 40k which had added garbage memory of 40k * 120kb → 4.8Gb each time you call that code.

If you want to actually execute this code every frame and the vertices aren’t changing in between the frames you should cache the vertices array in a member variable.