Почему «Избегайте перечислений, где вам нужны только целые числа» были удалены из подсказок по производительности Android?

175

Раздел «Избегайте перечислений, где вам нужны только целые числа» был удален из официальной документации разработчика . (См. Почему Android не использует больше перечислений? Для старого содержимого раздела)

Зачем? Было ли изменение в виртуальной машине Android, которое сделало совет устаревшим?

Тьерри-Дмитрий Рой
источник
2
Для справки вот декомпилированный байт-код для примера Shrubbery: https://gist.github.com/847418
Джош Ли
15
По состоянию на март 2014 года на следующей странице по-прежнему содержатся рекомендации против использования перечислений: developer.android.com/training/articles/memory.html#Overhead
Тахир Ахтар
2
Год спустя, как сказал @TahirAkhtar, официальное обучение по Android все еще говорит: «Вы должны строго избегать использования enums на Android».
LarsH
1
Интересно отметить, что рекомендация избегать enum содержится в этой статье от ведущего разработчика Android 2015 года: medium.com/google-developers/… Также: «Обратите внимание, что с помощью аннотации @IntDef, которая поддерживается в Android Studio и Gradle 1.3+, обеспечит безопасность типов кода во время сборки (если включены ошибки lint), сохраняя при этом преимущества размера и производительности при использовании переменных int. "
Тони
4
Начиная с апреля 2018 года, следующая страница больше не содержит рекомендаций против использования перечислений. developer.android.com/topic/performance/memory#Overhead
Робин Дэвис,

Ответы:

157

оригинальная версия этого документа была просто кучей предрассудков. он был переписан, чтобы содержать только факты, подкрепленные фактическими тестами, и он обновляется по мере обновления виртуальной машины. Вы можете найти различные тесты, а также некоторые тесты, которые мы используем для оптимизации основных библиотек, по адресу http://code.google.com/p/dalvik/ .

Эллиот Хьюз
источник
35
Было бы полезно, если бы вы указали свои учетные данные в своем профиле SO. Мне потребовалось немного покопаться. Но теперь, когда я вижу, что вы, кажется, работаете в команде VM, я приму ваш ответ в качестве официального ответа. :)
Тьерри-Дмитрий Рой
25
Добавление класса enum, конечно, означает, что ваше приложение содержит дополнительный класс, поэтому оно не является бесплатным , но мы должны предположить, что разработчик добавляет перечисления только там, где они полезны. Единственное действительно плохое использование enum, которое я видел, было в некотором коде гармонии, где они действительно хотели использовать int (для битовых масок и тому подобного), и «enum» не был enum в каком-либо разумном смысле. Если вы часто вызываете "ordinal ()", это, вероятно, неприятный запах, означающий, что вы не хотите перечислять. Но это не специфический для Android совет, и в любом случае это действительно редкая ошибка дизайна.
Эллиот Хьюз
17
Является ли этот документ устаревшим @ Thierry-DimitriRoy? В частности, вы должны строго избегать использования перечислений на Android.
Джейкоб Табак
3
FWIW, Proguard по умолчанию преобразует перечисления в целые .
Начо Колома
11
Ссылка, которую вы дали, мертва.
Терри
26

Догадка:

  • Гигагерцевые процессоры, такие как Hummingbird и Snapdragon, теперь широко распространены, а требования к малому объему памяти, которые изначально ограничивали виртуальную машину Dalvik, уже не соответствуют действительности.
  • Каждое отгрузочное устройство использует JIT (новинка до 2.2). Инициализатор класса enum будет работать быстрее, значения могут рассматриваться как константы времени JIT, а JIT вполне может иметь специальную поддержку для оптимизации классов enum.
  • Код, который действительно чувствителен к производительности, использует NDK, который все еще был новым и неполным, когда был выпущен Android 1.5. NDK в 2.3 поддерживает нативные действия, что позволяет почти полностью управлять играми.

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

Джош Ли
источник
23

Эллиот Хьюз предлагает более подробную информацию о переписывании документации в своем блоге: http://elliotth.blogspot.com/2010/09/java-benchmarks.html

Во второй половине поста объясняется, что каждое утверждение в документе Performance теперь подкреплено тестами. Предыдущие версии документа, очевидно, содержали непроверенные утверждения, такие как «Избегайте перечислений, потому что они слишком дороги».

jkooker
источник
Просто хотел дополнить принятый ответ Эллиотта этой ссылкой.
Jkooker
12

В ответе Elliot Hugues за 2011 год говорилось, что первоначальная причина избегать enum была по причине производительности ... как в "производительности обработки". Поскольку эта причина не была подкреплена фактом, она была удалена из официальной документации.

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

Тьерри-Дмитрий Рой
источник
2
Кроме того, ребята из Google представили IntDefаннотации, которые позволяют безопасно использовать int-константы с ошибками и предупреждениями Android Studio. blog.shamanland.com/2016/02/int-string-enum.html
Алексей К.
9

TLDR: Dalvik плохо справился с распределением памяти и Enumиспользует больше памяти, чем int. Android Lollipop заменил Dalvik на ART, который не страдает от тех же ограничений. Таким образом, эта рекомендация больше не актуальна.

Длинный ответ:

Вот Это Да! 8 лет, 5 ответов и много комментариев спустя настоящая причина до сих пор не устранена.

В дни Android, предшествующие леденцу на палочке, Dalvik был тем процессом, который использовала VM. Поскольку в то время приложениям было доступно небольшое количество памяти, у Дальвика было много ограничений по памяти. Для выделения памяти Далвику пришлось пройти кучу и найти место. Куча также со временем будет фрагментирована. Dalvik не может дефрагментировать, поэтому он будет распределяться с течением времени и в конечном итоге не хватит места.

Избегайте Enums, где вам нужны только Ints

приходит из далвикских дней, потому что Enumнамного больше, чемint и распределение памяти было очень дорого.

Вскоре, Dalvik был заменен на ART. ART вышел в KitKat и по умолчанию с Lollipop.

ART был создан с нуля не для оптимизации памяти, а для оптимизации производительности. Он также оптимизирован для распределений и сборов. Причина в том, что у него выделена память для больших объектов. Вместо того, чтобы помещать все в одну кучу, а затем находить место для больших объектов среди всех крошечных, ART помещает все большие объекты и растровые изображения в отдельную кучу. И тогда мелкие предметы уходят в отдельную кучу. Также это может дефрагментировать.

После АРТ, если вы используете Enum Android, это не волнует, и именно поэтому рекомендации сейчас нет.

Это от Чета Хаазе из Google. Я рекомендую найти его разговор Google I / O и смотреть все видео. Он содержит много полезной информации и понимания Android.

Адель Ахмад
источник