![](/img/trans.png)
[英]How to implement a ProgressDialog correctly so that time-consuming methods are called in background?
[英]Why doesn't profiler see one of time-consuming methods?
我正在尝试剖析多维数组类的两个实现思想。
在下面的代码中,应用程序创建了一个巨大的多维数组,该数组包含三个类: Array1
, Array2
和常规。
应用程序首先创建未测量的数组。 然后,它填充每个数组并按顺序读取每个数组。 时间测量既可以通过编程方式进行,也可以通过探查器进行。
不幸的是,节的时间安排不是一致的。 例如,在探查器中根本没有列出消耗将近一半时间的方法或类Array2。
为什么?
主要代码:
package tests;
public class Runner01 {
private static final int[] dims = {400, 100, 20, 300};
static private double[] data;
static private Array1 array1;
static private Array2 array2;
static private double[][][][] array3;
public static interface MyRunnable {
public void run(int ii, int i, int j, int k, int l);
}
public static long test(MyRunnable runnable) {
long start = System.nanoTime();
int ii = 0;
for (int i = 0; i < dims[0]; ++i) {
for (int j = 0; j < dims[1]; ++j) {
for (int k = 0; k < dims[2]; ++k) {
for (int l = 0; l < dims[3]; ++l) {
runnable.run(ii, i, j, k, l);
ii++;
}
}
}
}
long end = System.nanoTime();
System.out.println("Done in " + (double) (end - start) / 1000000000 + " seconds");
return end - start;
}
public static void main(String[] args) {
int ii;
long start, end, elapsed;
start = System.nanoTime();
System.out.println("Filling...");
int size = 1;
for (int i = 0; i < dims.length; ++i) {
size *= dims[i];
}
data = new double[size];
for (int i = 0; i < data.length; ++i) {
data[i] = Math.random();
}
array1 = new Array1(dims);
array2 = new Array2(dims);
array3 = new double[dims[0]][dims[1]][dims[2]][dims[3]];
System.out.println("Done.");
System.out.println("Writing array1...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
array1.set(data[ii], i, j, k, l);
}
});
System.out.println("Writing array2...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
array2.set(data[ii], i, j, k, l);
}
});
System.out.println("Writing array3...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
array3[i][j][k][l] = data[ii];
}
});
System.out.println("Reading array1...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
assert (data[ii] == array1.get(i, j, k, l));
}
});
System.out.println("Reading array2...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
assert (data[ii] == array2.get(i, j, k, l));
}
});
System.out.println("Reading array3...");
test(new MyRunnable() {
@Override
public void run(int ii, int i, int j, int k, int l) {
assert (array3[i][j][k][l] == data[ii]);
}
});
end = System.nanoTime();
elapsed = end - start;
System.out.println("Total application time is " + (double) (end - start) / 1000000000 + " seconds");
}
}
Array1代码:
package tests;
public class Array1 {
private Object delegate;
private Object allocate(Object delegate, int[] is, int pos) {
if (pos < is.length) {
delegate = new Object[is[pos]];
for (int k = 0; k < is[pos]; ++k) {
((Object[]) delegate)[k] = allocate(((Object[]) delegate)[k], is, pos + 1);
}
}
return delegate;
}
private Object get(Object delegate, int[] is, int pos) {
if (pos < is.length) {
Object subdelegate = ((Object[]) delegate)[is[pos]];
return get(subdelegate, is, pos + 1);
} else {
return delegate;
}
}
private void set(Object delegate, int[] is, int pos, double value) {
if (pos < is.length - 1) {
Object subdelegate = ((Object[]) delegate)[is[pos]];
set(subdelegate, is, pos + 1, value);
} else {
((Object[]) delegate)[is[pos]] = value;
}
}
public Array1(int... is) {
delegate = allocate(delegate, is, 0);
}
public double get(int... is) {
return (double) get(delegate, is, 0);
}
public void set(double value, int... is) {
set(delegate, is, 0, value);
}
}
Array2代码:
package tests;
public class Array2 {
private double[] delegate;
private int[] pows;
public Array2(int... is) {
pows = new int[is.length];
int size = 1;
for (int k = 0; k < is.length; ++k) {
pows[k] = size;
size *= is[k];
}
delegate = new double[size];
}
public double get(int... is) {
int pos = 0;
for (int k = 0; k < is.length; ++k) {
pos += is[k] * pows[k];
}
return delegate[pos];
}
public void set(double value, int... is) {
int pos = 0;
for (int k = 0; k < is.length; ++k) {
pos += is[k] * pows[k];
}
delegate[pos] = value;
}
}
结果:
您似乎具有第一和第四次运行的子呼叫配置文件,第二和第五次运行的单个呼叫配置文件,第三和第六次运行没有任何呼叫; 这些对应于Array1,Array2和内置的数组数组访问。 (您可以调用$ 1.run,$ 2.run,$ 4.run和$ 5.run,但没有$ 3.run和$ 6.run)
因此,对于您的三种情况,我猜第一种情况没有内联调用,第二种情况是对可运行对象的调用下的所有内容进行内联,第三种情况是在可运行对象内部仅看到简单的代码,因此它对测试下的所有内容进行内联(总计的打印时间中的101.36s与测试中分析器的101,373ms一致)。
有一些常见的方法可以在对Java进行微基准测试时忽略预热结果,并在此答案中提供了一些好的建议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.