Подтвердить что ты не робот

Производительность Java Enums?

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

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

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
}

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

Является ли мое предположение о том, что на самом деле то же самое можно использовать для перечисления в качестве статических констант, или я что-то здесь не вижу?

4b9b3361

Ответ 1

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

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

ИЗМЕНИТЬ

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

Сравнение перечислений выглядит следующим образом:

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");
    }
}

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

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

Ответ 2

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

Ответ 3

JIT оптимизирует много вещей, делая такие вещи, как это, не имеет значения после того, как оно работает некоторое время

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

Ответ 4

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