For-Loop Performance Oddity - PullRequest
       4

For-Loop Performance Oddity

1 голос
/ 25 апреля 2010

Я только что заметил кое-что, касающееся производительности цикла, которое, кажется, идет вразрез с рекомендациями, данными командой 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 оптимизирует умножение и использует предварительно вычисленный литерал?

1 Ответ

3 голосов
/ 25 апреля 2010

(8 * 320 * 480) абсолютно оптимизируется до 1228800 как «постоянная времени компиляции», когда создается код цикла for.

Ключевым выводом из документации по финалу является то, что вы не получаете привилегию неизменяемого статуса, и это не оптимизируется во время создания цикла for. Несмотря на то, что это локальная переменная, вы «можете» ее изменить (несмотря на ключевое слово final ) внутри цикла for, чтобы ее нельзя было преобразовать в литерал.

Окончательная переменная может быть назначена только один раз. Это назначение не дает переменный неизменный статус.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...