我想知道为什么在JavaCV中访问普通数组的元素和CvMat的元素时,处理时间会有如此大的差异。值得注意的是,当在我的计算机上运行以下代码时,普通Java数组需要0.8秒,而CvMat需要26秒以上。知道为什么访问CvMat这么慢吗?
// Declare a normal java array and a CvMat (requires JavaCV)
double ArrayJava[][] = new double[10000][10000];
CvMat ArrayJavaCV = CvMat.create(10000, 10000,CV_32F);
// Get current time
long startTime1 = System.currentTimeMillis();
// For each element, initialize with a value, get the value and increase it by 0.1 and put it back
for(int i=0; i<ArrayJava.length; i++){
for (int j =0; j<ArrayJava[1].length; j++){
ArrayJava[i][j] = i;
double val1 = ArrayJava[i][j] + 0.1;
ArrayJava[i][j] = val1;
}
}
// Compute processing time
long endTime1 = System.currentTimeMillis();
System.out.println("ArrayJava processing time: "+(endTime1 - startTime1)/1000.+" sec");
// Perform the same procedure for the CvMat
long startTime2 = System.currentTimeMillis();
for(int i=0; i<ArrayJavaCV.rows(); i++){
for (int j =0; j<ArrayJavaCV.cols(); j++){
ArrayJavaCV.put(i, j, i);
double val2 = ArrayJavaCV.get(i, j) + 0.1;
ArrayJavaCV.put(i, j, val2);
}
}
long endTime2 = System.currentTimeMillis();
System.out.println("ArrayJavaCV processing time: "+(endTime2 - startTime2)/1000.+" sec");
在像c++这样的本地语言中,通常的做法是使用getter (i = getCount())而不是直接访问字段(i = mCount)。对于c++来说,这是一个很好的习惯,在c#和Java等其他面向对象语言中也经常这样做,因为编译器通常可以内联访问,如果你需要限制或调试字段访问,你可以随时添加代码。
然而,这在Java上是一个坏主意。虚拟方法调用的开销比实例字段查找要大得多。遵循常见的面向对象编程实践并在公共接口中使用getter和setter是合理的,但在类中应该始终直接访问字段。
如果没有JIT,直接访问字段比调用简单的getter快3倍。使用JIT(直接字段访问和访问本地一样便宜),直接字段访问比调用普通的getter要快7倍。