Производительность Android - «Избегайте внутренних геттеров / сеттеров» - PullRequest
23 голосов
/ 16 июля 2011

Просто прочитайте это на сайте разработчика:

Избегайте внутренних геттеров / сеттеров

На родных языках, таких как C ++, распространенной практикой является использование геттеров (например,i = getCount ()) вместо прямого доступа к полю (i = mCount).Это отличная привычка для C ++, потому что компилятор обычно может встроить доступ, и если вам нужно ограничить или отладить доступ к полю, вы можете добавить код в любое время.

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

Без JIT прямой доступ к полям примерно в 3 раза быстрее, чем вызовтривиальный добытчик.С JIT (где прямой доступ к полю обходится дешевле, чем доступ к локальному), прямой доступ к полю примерно в 7 раз быстрее, чем вызов тривиального геттера.Это верно для Froyo, но улучшится в будущем, когда JIT встроит методы получения.

Обновление в 2019/05: В текущей версии вышеуказанный материал был удален изdocument!

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

 public class MyObject {

    public Object innerObject; // This would be private if I was using a getter

    public void doSomeStuff(){
          if(innerObject){        // Within class access like this
                 // ....
          }
    }

    public Object getInnerObject(){  // This would be removed if I was using field access
         return innerObject;
    }
 }

Но как насчет доступа из другого объекта ?:

 public class SecondObject {

      public void doSecondSomething(){
                MyObject ob = new MyObject();
                Object inner;

                //This is my question basically (from an Android performance perspective)   
                inner = ob.getInnerObject();
                // OR 
                inner = b.innerObject

       }

 }

Ответы [ 7 ]

31 голосов
/ 16 июля 2011

Повышение производительности при использовании внутренних геттеров и сеттеров также распространяется на внешние геттеры и сеттеры.

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

Повышение производительности является результатом ограничений старых JIT-компиляторов Android. Эта ситуация значительно улучшилась с Gingerbread (см. - https://stackoverflow.com/a/4930538/139985 ... и обратите внимание, кто написал этот ответ!) И продолжает улучшаться. Действительно, в текущей (2019 г.) версии Performance Tips весь раздел, содержащий рекомендации по внутренним методам получения и установки, был удален.

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

4 голосов
/ 16 июля 2011

Хотя b.innerObject быстрее, так как технология прогрессирует (лучше процессор, JIT и т. Д.), Разница между этими двумя вариантами уменьшается.

Единственный момент, когда это может иметь значение, это когда вы выполняете интенсивные циклы, которые выполняются постоянно. Например, в методе игры onDraw, когда вы перебираете сотни объектов.

3 голосов
/ 16 июля 2011

Имейте в виду, что эти соображения производительности актуальны только в том случае, если к рассматриваемому участнику обращаются тысячи раз в секунду.

Хорошим примером, когда прямой доступ может быть хорошей идеей, является сценарий игры ( libgdx )

public abstract class Actor {
    public Group parent;
    public final String name;
    public boolean touchable = true;

    public float x;
    public float y;
    public float width;
    public float height;
    public float originX;
    public float originY;
    public float scaleX = 1;
    public float scaleY = 1;
    public float rotation;
    public final Color color = new Color(1, 1, 1, 1);
3 голосов
/ 16 июля 2011
// this is faster
inner = b.innerObject

// but this won't hurt performance much because
// it's assumed that it will be rare
inner = ob.getInnerObject();
2 голосов
/ 16 июля 2011

С точки зрения производительности, нет разницы в доступе к this.field или that.field.

Ощущение, что поле экземпляра более доступно для объекта, на котором он размещен, - всего лишь иллюзия синтаксиса.

OO мудро, серьезно, насколько сложным может стать приложение для Android?Многие из ОО-мантр происходят из приложений монстров.Что может быть плохого, если ваше маленькое приложение использует объекты, подобные структурам?

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

2 голосов
/ 16 июля 2011

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

Я думаю, что вы тоженужно взглянуть на это с другой точки зрения:

  1. Не нарушит ли получатель / установщик распространенную практику упс?Вы не захотите иметь прямые ссылки, если вы создаете объекты / модули, которые будут использовать другие.

  2. Вы действительно не хотите использовать получатели / установщики слишком много раз, как в конце, если только sh! * Его оптимизированные вызовы функций не будут иметь издержек.

Вам действительно нужно оптимизировать для каждого отдельного случая, если я собираю два модуля, где некоторые компоненты доступны только друг другу, я мог бы создать статическое поле, в противном случае я буду придерживаться методов получения / установки

0 голосов
/ 22 марта 2016

Для записи, еще одна проблема с сеттерами и геттерами (в Java) заключается в том, что они болезненно уродливы для использования.

Скажем, в следующем упражнении нам нужно изменить поле внутри поля объекта

В Java это:

   object.getField().getSubField().setField3("hello"); // ugly

В то время как в C # тот же код (даже с инкапсуляцией)

   object.Field.SubField.Field3="hello";  // fine

Итак, использование открытого поля в Java (или Android)намного чище:

  object.field.subfield.field3="hello"; // fine too
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...