Должен ли я сделать Java объекты недействительными? - PullRequest
4 голосов
/ 02 марта 2012

Допустим, я перебираю массив объектов, т.е.

for (int r = 0; r < rows; r++) {
        for (int c = 0; c < columns; c++) {

            if (bricks[r][c] != null) {
                bricks[r][c].draw(gl)

Если я в какой-то момент захочу уничтожить кирпич, должен ли мой метод remove () аннулировать объект, например:

private void remove(GameBrick obj) {
     for (int r = 0; r < rows; r++) {
        for (int c = 0; c < columns; c++) {
        if (bricks[r][c] != null){
        if (bricks[r][c] == obj) {
            bricks[r][c] = null;
        } 

Или лучше установить флаг boolean exists в значение false, и при итерации объектов добавить оператор return или continue, если bricks[r][c].exists == false?

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

Я хочу знать, правда ли это, и что я должен сделать лучше всего, чтобы удалить объекты (если я даже должен).

Ответы [ 7 ]

4 голосов
/ 02 марта 2012

, но позже я прочитал о сборщике мусора и том, что установка объекта на ноль заставляет его запускаться чаще.

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

Установка ссылок на ноль - это способ, которым вы сообщаете ГХ, что вам нетбольше не нужен объект.GC не должен ничего с этим делать немедленно.

Обновление

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

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

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

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

3 голосов
/ 02 марта 2012

Позже я прочитал о сборщике мусора и что установка объекта на ноль делает его более частым.

Это не правда. Сборщик мусора работает по регулярному расписанию и когда JVM не хватает памяти. Установив ссылку на null, вы можете только увеличить объем памяти, который освобождает GC, и уменьшить объем работы, которую он выполняет, поскольку тип GC, используемый в java, равен O (| non-garbage-memory |) .

Увеличение объема освобождаемой памяти уменьшает O (| non-garbage-memory |), который может только заставить JVM исчерпывать память реже и не влияет на регулярно запланированные запуски.

Что я должен сделать лучше всего, чтобы удалить объекты (если я даже должен)?

Если ссылка на объект больше не нужна, установите для него значение null. Структурируйте свои функции так, чтобы вызовы функций, которые занимают много времени, принимали как можно меньше параметров. Структурируйте свои классы так, чтобы они были слабо связаны - один из результатов этого состоит в том, что у долгоживущих объектов мало членов. Делайте это последовательно, и вы окажетесь в том лучшем месте, для которого оптимизаторы JVM оптимизировали.

2 голосов
/ 02 марта 2012

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

1 голос
/ 02 марта 2012

Ответ будет зависеть от вашего конкретного кода, но в целом для игры на андроид вы хотите избежать как можно большего количества сбора мусора и создания объектов (см. здесь для некоторых деталей).

Знаете ли вы максимальное количество строк и столбцов кирпичей у вас будет? Будете ли вы разрушать и создавать кирпичи очень часто? Если это так, вам лучше всего выделить все свои кирпичи заранее и использовать логическое значение, чтобы указать, является ли кирпич живым или нет.

1 голос
/ 02 марта 2012

Да, установите ссылки на ноль.Это заставит сборщик мусора освободить больше памяти для вашего приложения.Установка ссылок на null не приводит к более частому запуску сборщика мусора, но, безусловно, поможет освободить больше памяти.

0 голосов
/ 02 марта 2012

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

Является ли это хорошей идеей или нет в вашем конкретном случае - это отдельная история.Конечно, вы можете свести к минимуму сборку мусора, не выделяя и не освобождая объекты (см. в этой презентации Google I / O ).Мне было бы интересно увидеть доказательства обратного от других, которые, кажется, не согласны.Если ваш 2D-массив является единственной ссылкой на кирпичи, то установка его в null будет разыменовывать объект.Хотя разыменование объекта может не заставлять GC работать чаще (я не уверен в этом, хотя вся литература, которую я прочитал, рекомендует избегать как разыменования, так и выделения в игровом цикле на Android), выделениенесомненно, будет.

Если ваши кирпичи всегда находятся в одной и той же позиции, и они просто разрушаются (как Breakout / Arkanoid), тогда ваша идея с булевым флагом, вероятно, является хорошей.В этом случае ваш 2D-массив действует как пул фиксированного размера.

Если ваши кирпичи могут менять позиции, вы могли бы делать то же самое и менять кирпичи при перемещении, ноиногда может быть более естественным просто добавить / удалить нормально.В этом случае вы должны разместить свои блоки в пуле заранее, а затем вы можете обнулить ссылку в своем двумерном массиве, не беспокоясь о сборке мусора, потому что в вашем пуле все еще есть ссылка (но сначала вам нужно будет выпустить ее обратно в пул).

0 голосов
/ 02 марта 2012

Подумайте о сохранении позиции r / c внутри кирпича, когда вы прикрепите его к контейнеру bricks. Тогда вам не нужно искать, просто загляните внутрь кирпича. Это предполагает, что вы можете добавить кирпич не более одного раза в контейнер.

Устанавливайте ссылку на null во всех случаях, когда содержащий объект живет дольше, чем область вашего кода. Не требуется устанавливать нулевые локальные переменные, это будет подразумеваться в конце области (конец блока "}").

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