【发布时间】:2014-11-09 21:57:17
【问题描述】:
我最近开始阅读有关基准测试并为 Android 编写它们(用 Java 编写)。我知道诸如预热、垃圾收集器和编译器优化等问题,但不知道我面临的问题是否是由这些问题引起的。
在我的基准测试应用程序中,我创建了一个包含 10,000 个浮点变量的数组,并使用随机值对其进行初始化。 运行基准代码时:
private void runMinorBenchmarkFloat (float[] array) {
float sum = 0;
long startTime;
long endTime;
/* Fast warm-up */
startTime = System.nanoTime();
for(int i=0; i<SMALL_LOOP_ITERATION_COUNT; i++)
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
endTime = System.nanoTime() - startTime;
postMessage("Warm-up for FLOAT finished in: " + endTime/1000000 + "ms.\n");
/* Main benchmark loop */
startTime = System.nanoTime();
for(int i=0; i<BIG_LOOP_ITERATION_COUNT; i++)
{
sum = 0;
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
}
endTime = System.nanoTime() - startTime;
postMessage("Benchmark for FLOAT finished in: " + endTime/1000000 + "ms.\n");
postMessage("Final value: " + sum + "\n\n");
}
在我的手机上,我有大约 2 秒的预热时间和 20 秒的“真实”循环时间。
现在,当我再添加两个浮点变量(sum2 和 sum3 - 从未在方法中使用)时:
private void runMinorBenchmarkFloat (float[] array) {
float sum = 0, sum2 = 0, sum3 = 0; // <------- the only code change here!!!
long startTime;
long endTime;
/* Fast warm-up */
startTime = System.nanoTime();
for(int i=0; i<SMALL_LOOP_ITERATION_COUNT; i++)
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
endTime = System.nanoTime() - startTime;
postMessage("Warm-up for FLOAT finished in: " + endTime/1000000 + "ms.\n");
/* Main benchmark loop */
startTime = System.nanoTime();
for(int i=0; i<BIG_LOOP_ITERATION_COUNT; i++)
{
sum = 0;
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
}
endTime = System.nanoTime() - startTime;
postMessage("Benchmark for FLOAT finished in: " + endTime/1000000 + "ms.\n");
postMessage("Final value: " + sum + "\n\n");
}
执行时间从预热的 2 秒跳到 5 秒,从真正循环的 20 秒跳到 50 秒。
常量:
SMALL_LOOP_ITERATION_COUNT = 100,000
BIG_LOOP_ITERATION_COUNT = 1,000,000
您认为这种差异可能是由对齐问题引起的吗(只是松散的想法)?
提前感谢您的任何回答。
编辑:
似乎并非所有设备都出现此错误。我可以在三星 Galaxy S5 上重现它。 该计划的主要目标是做很少的基准测试。我做了四个几乎相同的函数(runMinorBenchmark____,其中 _ 是:int、short、float、double),仅在变量“sum”类型上有所不同。在主基准函数中,我调用了这些函数。因为发生了上述错误,我决定将这些功能合并为一个大功能。 现在......在运行测试时,我有这样的时间: 1. 37640 毫秒。 (对于整数) 2. 46728 毫秒。 (简称) 3. 60589 毫秒。 (用于浮动) 4. 34467 毫秒。 (双)
我知道由于类型转换,short 意味着更慢。我还认为浮点数在将其转换为双倍的情况下应该更慢(也许 FPU 每次都会将类型转换为双倍(?))。但是,当我将 sumFloat 的变量类型从 float 更改为 double 时,float 的时间与 double 时间相同。 我还在另一台设备上做了这个“基准测试”,它似乎没有受到这种奇怪行为的影响,每次测试的时间几乎相同:~45000ms。 (真的没有明显的差异)。
Dalvik VM 错误 (?)
【问题讨论】:
-
没有。添加两个“未使用”字段不会影响循环的实际运行时间。肯定有其他问题。
-
我同意@TheLostMind。添加两个浮点变量应该不会显着增加您的执行时间。如您所见,CPU 可以非常快速地处理 10,000 个浮点数,因此它没有理由不能快速处理这两个。
-
感谢您的回答。我同意你们俩的观点,但这就是真正发生的事情。你有什么想法可以进一步研究吗?
-
假设从投票中有人尝试成功地复制此问题,任何人都可以确认这是一个可以复制的问题吗?如果是这样,这是一个很棒的问题(抱歉,我现在没有能力自己测试)。
-
您在哪里运行这些功能?在 OnCreate() 或其他地方?我会尝试重现它。如果可以的话,你能把整个活动放上来供参考吗?
标签: java android performance-testing