So I’m not hijacking a different thread…
I’ve been asking Riven the fastest ways of using FloatBuffers after having some real performance issues with using them for a lot of values. I made a simple profiler and get really weird results.
Generating array of 524288 values to use...
Done.
Copying all values into a new array, then bulk putting (using nonexisting array and FloatBuffer)...
Took 0.011403 seconds.
Copying all values into a new array, then bulk putting (using existing array and FloatBuffer)...
Took 0.015468 seconds.
Using index-based puts (using nonexisting FloatBuffer)...
Took 0.006779 seconds.
Using individual puts (using nonexisting FloatBuffer)...
Took 0.006532 seconds.
This looks totally opposite. Individual inserts are really fast and bulk inserts are quite slow. This is Java 1.6.
Okay wait. I just ran it again with more values and the timing is across the map.
Generating array of 8388608 values to use...
Done.
Copying all values into a new array, then bulk putting (using nonexisting array and FloatBuffer)...
Took 0.119186 seconds.
Copying all values into a new array, then bulk putting (using existing array and FloatBuffer)...
Took 0.035243 seconds.
Using index-based puts (using nonexisting FloatBuffer)...
Took 0.074629 seconds.
Using individual puts (using nonexisting FloatBuffer)...
Took 0.058328 seconds.
Here is the really quick and dirty code. Is it a bad idea to use nanoTime? Am I not warming it up correctly?
import java.nio.FloatBuffer;
public class FloatBufferProfiler
{
public static void main(String[] args)
{
final int ARRAY_SIZE = 8388608;
final double NANO = 1000000000.0;
System.out.println("Generating array of " + ARRAY_SIZE + " values to use...");
float[] valueArray = new float[ARRAY_SIZE];
for (int i = 0; i < valueArray.length; i++)
{
valueArray[i] = (float) (Math.random() * 100000);
}
System.out.println(" Done.");
//Warm up the clock.
long timePoll = System.nanoTime();
timePoll = System.nanoTime();
timePoll = System.nanoTime();
timePoll = System.nanoTime();
timePoll = System.nanoTime();
timePoll = System.nanoTime();
System.out.println("Copying all values into a new array, then bulk putting (using nonexisting array and FloatBuffer)...");
float[] newValues = new float[ARRAY_SIZE];
FloatBuffer buffer = FloatBuffer.allocate(ARRAY_SIZE);
for (int i = 0; i < valueArray.length; i++)
{
newValues[i] = valueArray[i];
}
buffer.put(newValues);
buffer.flip();
System.out.println(" Took " + ((System.nanoTime() - timePoll) / NANO) + " seconds.");
System.out.println("Copying all values into a new array, then bulk putting (using existing array and FloatBuffer)...");
timePoll = System.nanoTime();
buffer.clear();
for (int i = 0; i < valueArray.length; i++)
{
newValues[i] = valueArray[i];
}
buffer.put(newValues);
buffer.flip();
System.out.println(" Took " + ((System.nanoTime() - timePoll) / NANO) + " seconds.");
System.out.println("Using index-based puts (using nonexisting FloatBuffer)...");
buffer.clear();
buffer = null;
timePoll = System.nanoTime();
buffer = FloatBuffer.allocate(ARRAY_SIZE);
for (int i = 0; i < valueArray.length; i++)
{
buffer.put(i, valueArray[i]);
}
buffer.flip();
System.out.println(" Took " + ((System.nanoTime() - timePoll) / NANO) + " seconds.");
System.out.println("Using individual puts (using nonexisting FloatBuffer)...");
buffer.clear();
buffer = null;
timePoll = System.nanoTime();
buffer = FloatBuffer.allocate(ARRAY_SIZE);
for (int i = 0; i < valueArray.length; i++)
{
buffer.put(valueArray[i]);
}
buffer.flip();
System.out.println(" Took " + ((System.nanoTime() - timePoll) / NANO) + " seconds.");
}
}
The four situations I was testing are:
- A new array and buffer is made every draw pass. All the values are copied over into the array one by one (simulating what you would be doing making draw calls from all over your code), then bulk copied to the buffer.
- An existing array and buffer have already been made, so are in memory. The buffer is cleared. Then the above operation happens (basically the same as above with a clear instead of making a new buffer and array it just clears them out).
- No array is used, a new buffer is made every draw pass. A bunch of individual puts happen, each one using the index value.
- No array is used, a new buffer is made every draw pass. A bunch of individual puts happen, with no index value.
This seems to vary wildly based on the number of items I’m putting in. Wha?