Производительность Java Enums? - PullRequest
17 голосов
/ 06 ноября 2011

Я реализую игру для двух игроков, которая будет работать в тесном цикле буквально сотни тысяч раз, и тогда будет иметь первостепенное значение для производительности.

Мой код выглядит примерно так:

public class Table {
    private final int WHITE_PLAYER = +1;
    private final int BLACK_PLAYER = -1;

    private final int currentPlayer;
    private final int otherPlayer;

    ...
}

Мне было интересно, получу ли я какой-нибудь удар по производительности, выберу ли я вместо

private final int WHITE_PLAYER = +1;
private final int BLACK_PLAYER = -1;

перечисление, определенное как

public enum Players {
    WhitePlayer,
    BlackPlayer
}

У меня была идея, что перечисления были простосинтаксический сахар над целочисленными константами и тщательный анализ байт-кода, сгенерированного для тестового перечисления, а также вызывающего его кода, похоже, указывают на то, что их использование действительно то же самое, что и вызов статического метода, но для некоторой инфраструктуры перечисления, котораяустанавливается при первом запуске.

Предполагается ли, что использование перечислений в качестве статических констант действительно одинаково, или я что-то здесь упустил?

Ответы [ 4 ]

21 голосов
/ 06 ноября 2011

В микропроцессоре да, проверка равенства целочисленных констант будет быстрее, чем проверка равенства констант перечислений.

Однако в реальном приложении, не говоря уже об игре, это будет совершенно неактуально. То, что происходит в подсистеме AWT (или любом другом инструментарии GUI), затмевает эти соображения по поводу микропроизводительности на много порядков.

EDIT

Позвольте мне немного подробнее остановиться.

Сравнение перечислений выглядит так:

aload_0
getstatic
if_acmpne

Целочисленное сравнение для небольшого целого числа выглядит так:

iload_0
iconst_1
if_icmpne

Очевидно, что первая работа больше, чем вторая, хотя разница довольно мала.

Запустите следующий контрольный пример:

class Test {

    static final int ONE = 1;
    static final int TWO = 2;

    enum TestEnum {ONE, TWO}

    public static void main(String[] args) {
        testEnum();
        testInteger();
        time("enum", new Runnable() {
            public void run() {
                testEnum();

            }
        });
        time("integer", new Runnable() {
            public void run() {
                testInteger();
            }
        });
    }

    private static void testEnum() {
        TestEnum value = TestEnum.ONE;
        for (int i = 0; i < 1000000000; i++) {
            if (value == TestEnum.TWO) {
                System.err.println("impossible");
            }
        }
    }

    private static void testInteger() {
        int value = ONE;
        for (int i = 0; i < 1000000000; i++) {
            if (value == TWO) {
                System.err.println("impossible");
            }
        }
    }

    private static void time(String name, Runnable runnable) {
        long startTime = System.currentTimeMillis();
        runnable.run();
        System.err.println(name + ": " + (System.currentTimeMillis() - startTime) + " ms");
    }
}

и вы обнаружите, что сравнение перечислений медленнее, чем сравнение целых чисел, на моей машине примерно на 1,5%.

Все, что я говорил, это то, что это различие не будет иметь значения в реальном приложении («Преждевременная оптимизация - корень всего зла»). Я имею дело с проблемами производительности на профессиональном уровне (см. Мой профиль), и я никогда не видел горячей точки, которая может быть связана с чем-то вроде этого.

11 голосов
/ 06 ноября 2011

Вы должны позаботиться о том, чтобы иметь хороший и читаемый код, прежде чем заботиться о производительности. Пока ваши результаты профилирования (не догадайтесь!) Не покажут, что перечисления являются узким местом, забудьте о производительности и используйте все, что легче понять.

2 голосов
/ 06 ноября 2011

JIT оптимизирует многие вещи, делая такие вещи неактуальными после того, как он какое-то время работал

не говоря уже о том, что перечисления более читабельны и более надежны, если вы допустите ошибку в своем коде

0 голосов
/ 07 ноября 2011

Ваше предположение верно. Java гарантирует, что существует только один экземпляр перечисления, так что == столь же эффективен, как и сравнение целых чисел.

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