我编写了两个版本的程序来测试 java 程序中对象分配对性能的影响。一个使用简单的java对象:
class Point {
public final double x;
public final double y;
public Point(double a, double b) {
x = a;
y = b;
}
public double len() {
return Math.sqrt(x*x + y*y);
}
public Point minus(Point o) {
return new Point(x-o.x, y-o.y);
}
}
// ...
public static void test () {
Point[] points = new Point[size];
for (int i=0; i<size; i++) {
points[i] = new Point(rnd.nextDouble(), rnd.nextDouble());
}
double sum = 0;
for (int i=0; i<size; i++) {
for (int j=i; j<size; j++) {
sum += points[i].minus(points[j]).len();
}
}
}
和其他将 java 对象扁平化为局部变量:
class PointStatic {
static class PointBuffer {
double x;
double y;
}
static public double len(double x, double y) {
return Math.sqrt(x*x + y*y);
}
static public void minus(double x, double y, double o_x, double o_y, PointBuffer b) {
b.x = x - o_x;
b.y = y - o_y;
}
}
// ...
public static void test () {
double[] points_x = new double[size];
double[] points_y = new double[size];
for (int i=0; i<size; i++) {
points_x[i] = rnd.nextDouble();
points_y[i] = rnd.nextDouble();
}
double sum = 0;
PointStatic.PointBuffer b = new PointStatic.PointBuffer();
for (int i=0; i<size; i++) {
for (int j=i; j<size; j++) {
PointStatic.minus(points_x[i], points_y[i], points_x[j], points_y[j], b);
sum += PointStatic.len(b.x, b.y);
}
}
System.gc();
}
两个测试都完成了相同的(计算繁重的)任务,唯一的区别是后者不分配任何点对象。我使用以下运行器来测试这些实现:
static int size = 50000;
static int iters = 5;
public static void main (String[] args) throws InterruptedException {
for (int i=0; i<iters; i++) {
System.out.println(i);
Thread[] threads = new Thread[8];
for (int j=0; j<8; j++) {
threads[j] = new Thread(new Runnable() {
public void run() { test(); }
});
threads[j].start();
}
for (int j=0; j<8; j++) {
threads[j].join();
}
System.gc();
}
}
在我的机器上,第一个版本用了 2:36 分钟,第二个(优化的)版本用了 2:29 分钟。如您所见,差异可以忽略不计!这是否意味着 jit 编译器使要在 java 12 中添加的值类型无用?
我的测试用例可能不是 L-world 值类型的良好模拟。在那种情况下,瓦尔哈拉项目的 L 世界价值观类型背后的基本概念是什么?