Я только что заметил кое-что, касающееся производительности цикла, которое, кажется, идет вразрез с рекомендациями, данными командой Google Android. Посмотрите на следующий код:
package com.jackcholt;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
public class Main extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
loopTest();
finish();
}
private void loopTest() {
final long loopCount = 1228800;
final int[] image = new int[8 * 320 * 480];
long start = System.currentTimeMillis();
for (int i = 0; i < (8 * 320 * 480); i++) {
image[i] = i;
}
for (int i = 0; i < (8 * 320 * 480); i++) {
image[i] = i;
}
Log.i("loopTest", "Elapsed time (recompute loop limit): " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < 1228800; i++) {
image[i] = i;
}
for (int i = 0; i < 1228800; i++) {
image[i] = i;
}
Log.i("loopTest", "Elapsed time (literal loop limit): " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < loopCount; i++) {
image[i] = i;
}
for (int i = 0; i < loopCount; i++) {
image[i] = i;
}
Log.i("loopTest", "Elapsed time (precompute loop limit): " + (System.currentTimeMillis() - start));
}
}
Когда я запускаю этот код, я получаю следующий вывод в logcat:
I/loopTest( 726): Elapsed time (recompute loop limit): 759
I/loopTest( 726): Elapsed time (literal loop limit): 755
I/loopTest( 726): Elapsed time (precompute loop limit): 1317
Как вы можете видеть, код, который, кажется, пересчитывает значение предела цикла на каждой итерации цикла, очень хорошо сравнивается с кодом, который использует литеральное значение для предела цикла. Однако код, который использует переменную, которая содержит предварительно вычисленное значение для предела цикла, значительно медленнее, чем любой другой. Я не удивлен, что доступ к переменной должен быть медленнее, чем при использовании литерала, но почему код, который выглядит так, как будто он должен использовать две инструкции умножения на каждой итерации цикла, настолько сопоставимый по производительности с литералом?
Может ли быть так, что, поскольку литералы - это единственное, что умножается, компилятор Java оптимизирует умножение и использует предварительно вычисленный литерал?