-
Enhancement
-
Resolution: Won't Fix
-
P5
-
9, 10
-
generic
-
generic
A DESCRIPTION OF THE REQUEST :
Please refer to the source code to understand what's going on.
Points of interest:
This will be stack allocated:
float[] m = new float[16];
Mat mat = new Mat(m)
This will not:
Mat mat = new Mat(new float[16])
Run the JVM with -verbose:gc flag and see the output.
JUSTIFICATION :
I don't see any good reason why this behaviour would be justified, since the workaround is really simple.
This suggests the compiler is being silly nad not recognizing a situation where a very simple optimization could be used.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Escape analysis should be able to optimize all of the examples below.
ACTUAL -
It only optimizes the first one.
GC activity suggests that objects in example 2 and 3 are being allocated on heap. (run with -verbose:gc flag)
---------- BEGIN SOURCE ----------
public class StackAllocationTest {
public static void main(String[] args) {
System.out.println("TEST1, new Mat(m)");
test1();
System.out.println("TEST2, new Mat(new float[16])");
test2();
System.out.println("TEST2, new Mat()");
test3();
}
static void test1() {
float result = 0;
for(int i=0; i<100000000; i++) {
float[] m = new float[16];
Mat mat = new Mat(m);
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static void test2() {
float result = 0;
for(int i=0; i<100000000; i++) {
Mat mat = new Mat(new float[16]);
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static void test3() {
float result = 0;
for(int i=0; i<100000000; i++) {
Mat mat = new Mat();
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static class Mat {
final float[] matrix;
public Mat(float[] mat) {
this.matrix = mat;
}
public Mat() {
this.matrix = new float[16];
}
public void set(float x, float y, float z) {
matrix[12] = x;
matrix[13] = y;
matrix[14] = z;
}
public void mul(float scale) {
matrix[12] *= scale;
matrix[13] *= scale;
matrix[14] *= scale;
}
public float getX() {
return matrix[12];
}
public float getY() {
return matrix[13];
}
public float getZ() {
return matrix[14];
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Allocate float[] first, then pass it to the constructor of a wrapper object
Please refer to the source code to understand what's going on.
Points of interest:
This will be stack allocated:
float[] m = new float[16];
Mat mat = new Mat(m)
This will not:
Mat mat = new Mat(new float[16])
Run the JVM with -verbose:gc flag and see the output.
JUSTIFICATION :
I don't see any good reason why this behaviour would be justified, since the workaround is really simple.
This suggests the compiler is being silly nad not recognizing a situation where a very simple optimization could be used.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Escape analysis should be able to optimize all of the examples below.
ACTUAL -
It only optimizes the first one.
GC activity suggests that objects in example 2 and 3 are being allocated on heap. (run with -verbose:gc flag)
---------- BEGIN SOURCE ----------
public class StackAllocationTest {
public static void main(String[] args) {
System.out.println("TEST1, new Mat(m)");
test1();
System.out.println("TEST2, new Mat(new float[16])");
test2();
System.out.println("TEST2, new Mat()");
test3();
}
static void test1() {
float result = 0;
for(int i=0; i<100000000; i++) {
float[] m = new float[16];
Mat mat = new Mat(m);
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static void test2() {
float result = 0;
for(int i=0; i<100000000; i++) {
Mat mat = new Mat(new float[16]);
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static void test3() {
float result = 0;
for(int i=0; i<100000000; i++) {
Mat mat = new Mat();
mat.set(i, i, i);
mat.mul(0.5f);
result += mat.getX() + mat.getY() - mat.getZ();
}
System.out.println("Result: " + result);
}
static class Mat {
final float[] matrix;
public Mat(float[] mat) {
this.matrix = mat;
}
public Mat() {
this.matrix = new float[16];
}
public void set(float x, float y, float z) {
matrix[12] = x;
matrix[13] = y;
matrix[14] = z;
}
public void mul(float scale) {
matrix[12] *= scale;
matrix[13] *= scale;
matrix[14] *= scale;
}
public float getX() {
return matrix[12];
}
public float getY() {
return matrix[13];
}
public float getZ() {
return matrix[14];
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Allocate float[] first, then pass it to the constructor of a wrapper object