#android #garbage-collection #arraylist
#Android #сборка мусора #arraylist
Вопрос:
Я разрабатываю игру для Android, и у меня есть вопрос о сохранении игровых элементов без запуска сборщика мусора.
Моей игре нужна коллекция, в которой игровые элементы хранятся в соответствии с позициями x, y (все игровые элементы имеют x, y, ширину и высоту). Затем коллекция вызывается каждый кадр для повторного просмотра элементов в соответствии с размерами камеры, разрешением, шириной и высотой камеры (пользователь может прокручивать игру).
Пример:
function draw() {
tmp = collection.getElements(tmp,cameraX,cameraY,cameraWidth,cameraHeight);
for(int i = 0; i < tmp.size(); i ) {
tmp.get(i).draw();
}
}
В настоящее время я использую класс Vector для представления элементов коллекции, но gc продолжает запускаться каждые пару минут. Я делаю все свои распределения заранее. Я также изменил функцию getElements, чтобы принимать еще 1 параметр — временной вектор (выделенный заранее), который заполняется элементами, а затем возвращается.
- В каком классе хранить игровые элементы, чтобы gc не запускался (я предпочитаю, чтобы никогда, если это возможно)?
- я также добавляю элементы в коллекцию во время выполнения, должен ли я также выделять их заранее?
Спасибо,
С уважением Дж.
Ответ №1:
- Если у вас есть ссылка на объект, GC не будет их собирать. Итак, если вы не создаете объекты (и не освобождаете их) во время игры, ваш GC никогда не освободит память
- Если вам нужно создать свои элементы заранее, зависит от типа элементов. Если они должны считывать данные из файловой системы, вы должны загрузить их раньше в последовательности загрузки. Если они просты, вы можете сделать это, когда они понадобятся вам в первый раз
Комментарии:
1. GC должен запускаться, чтобы определить, есть ли ссылка, поэтому логика # 1 ошибочна. (Конечно, вполне возможно, что он никогда не запустится, если нет новых выделений.)
2. @delnan Верно, но это не приведет к сбою, который появляется, когда он фактически освобождает часть памяти, верно?
3. Настоящим узким местом цикла GC является остановка выполнения для определения доступности, а не фактическое освобождение памяти (при копировании GCS это немного важнее, но все же не основная причина замедления).
4. я заметил, что приведенный ниже код запускает gc, есть идеи, как это обойти? во время (запуска) { try { c = holder.lockCanvas(null); synchronized (holder) { // render } } finally { // сделайте это в finally, чтобы в случае возникновения исключения // во время вышеописанного, мы не оставили Surface в // несогласованном состоянии, если (c != null) { holder.unlockCanvasAndPost(c); } } }
5. @Delnan у тебя есть ресурс для этого? Потому что мой опыт до сих пор таков, что GC создает задержки при освобождении памяти, особенно больших объемов, и никогда не создает никаких задержек, когда он просто запускается, ничего не освобождая.
Ответ №2:
Возможно, сейчас не стоит беспокоиться о проблеме, возникающей раз в несколько минут, вы получаете заметное падение частоты кадров при ее срабатывании? Другой вариант — просто вызвать System.gc(), когда вам удобно.
Комментарии:
1.
System.gc()
это простоit would be nice if you do it now
, но это не фактический вызов для немедленного запуска GC2. мне удалось настроить код так, чтобы он вызывался каждые 10 минут или чаще, но это заметно. Но на самом деле не знаю, почему это вызывается (код всегда один и тот же, ничего нового не запускается).. Это из-за вектора или эмулятора? В logcats говорится, что GC_FOR_MALLOC освободил X объектов / X байт за 180 мс..
3. @jarnej, это 180 мс на аппаратном обеспечении или на эмуляторе? Эмулятор работает довольно медленно, и ваша производительность в реальном мире должна быть лучше. Отслеживаете ли вы количество кадров между сборками мусора? Мне любопытно узнать, окажется ли это 1 объектом / фреймом или чем-то еще.
4. в эмуляторе.. я использовал ddms и увидел выделение, которое было моей ошибкой: P я исправил это и теперь проверяю, сработает ли оно снова