实际上,在测试一些与OpenGL相关的代码时,我发现在私有字段上使用final修饰符可能会降低性能。以下是我测试的类的开头:
public class ShaderInput {
private float[] input;
private int[] strides;
public ShaderInput()
{
this.input = new float[10];
this.strides = new int[] { 0, 4, 8 };
}
public ShaderInput x(int stride, float val)
{
input[strides[stride] + 0] = val;
return this;
}
这是我用来测试各种替代方案性能的方法,其中包括ShaderInput类:
public static void test4()
{
int arraySize = 10;
float[] fb = new float[arraySize];
for (int i = 0; i < arraySize; i++) {
fb[i] = random.nextFloat();
}
int times = 1000000000;
for (int i = 0; i < 10; ++i) {
floatVectorTest(times, fb);
arrayCopyTest(times, fb);
shaderInputTest(times, fb);
directFloatArrayTest(times, fb);
System.out.println();
System.gc();
}
}
第三次迭代后,虚拟机已经热身,我始终得到这些数字没有最终关键字:
Simple array copy took : 02.64
System.arrayCopy took : 03.20
ShaderInput took : 00.77
Unsafe float array took : 05.47
使用final关键字:
Simple array copy took : 02.66
System.arrayCopy took : 03.20
ShaderInput took : 02.59
Unsafe float array took : 06.24
注意ShaderInput测试的数字。
无论我将字段设置为公共或私有都没有关系。
顺便说一下,还有一些令人困惑的事情。ShaderInput类在性能上优于所有其他变体,即使使用final关键字也是如此。这很显著,因为它基本上是一个包装浮点数组的类,而其他测试直接操作数组。必须弄清楚这个问题。可能与ShaderInput的流畅界面有关。
此外,System.arrayCopy对于小型数组实际上比在for循环中从一个数组复制元素到另一个数组要慢一些。使用sun.misc.Unsafe(以及直接的java.nio.FloatBuffer,在此处未显示)表现极差。