I recently found System.arraycopy() in my quest to make my level editor faster (I just implemented batch rendering and building vbos with 1.5 billion floats takes a while…) and I was going to tell you that I increased my build method’s speed by 26x (~175,500ms to ~6,600ms).
Which is still slow, but pretty good none the less, then I realized that I was reading my profiler wrong and I actually decreased the method time to ~460ms!!! 381X increase in performance! It’s pretty basic stuff, but I find it pretty cool so I figured that I’d share more.
Here’s what I was doing initially:
for(int i = 0; i < m_new_terrain_objects.size(); i++)
{
//Get the object
TerrainObject object = m_new_terrain_objects.get(i);
//Set the vertex offset for this object
object.setBatchVertexOffset(m_vertex_array.length);
//copy the vertex array from the object
float[] src_vertices = createInterleavedArray(object.getTransform(), object.getMesh().getVertices());
//build a temp array of the current vertex size plus the new vertex array size,
//so that the new info can be added
float[] temp_array = new float[m_vertex_array.length + src_vertices.length];
//now copy the current vertex data into the temp array
System.arraycopy(m_vertex_array, 0, temp_array, 0, m_vertex_array.length);
//now copy the new object's data into the temp array
//at the proper offset (the length of the current vertex array)
System.arraycopy(src_vertices, 0, temp_array, m_vertex_array.length, src_vertices.length);
//now update the current vertex array to reflect the changes
m_vertex_array = temp_array;
}
temporary array copies, building a new array every time, and basically utter nonsense. I thought a little more about it and I refactored:
int size = 0;
for(int i = 0; i < m_new_terrain_objects.size(); i++)
{
size += m_new_terrain_objects.get(i).getMesh().getVertices().length * (Vertex.SIZE - 4);
}
float[] temp_array = new float[m_vertex_array.length + size];
System.arraycopy(m_vertex_array, 0, temp_array, 0, m_vertex_array.length);
int current_index = m_vertex_array.length;
for(int i = 0; i < m_new_terrain_objects.size(); i++)
{
TerrainObject object = m_new_terrain_objects.get(i);
object.setBatchVertexOffset(current_index);
float[] src_vertices = createInterleavedArray(object.getTransform(), object.getMesh().getVertices());
System.arraycopy(src_vertices, 0, temp_array, current_index, src_vertices.length);
current_index += src_vertices.length;
}
m_vertex_array = temp_array;
There was no real way for me to get around figuring out the final array size so I have to touch every new object and find how many vertices there will be. Then I build one temp array to hold the final data and proceed to fill it up with all them floats.
Now I do have another function (createInterleavedArray()) that still builds a new array of the mesh data that I could just store, but I prefer it in a more readable format, the batched objects are only built in the level editor, and I already have good enough performance in this area.