Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 11.10.2011, 21:52
1g0rrr вне форума Посмотреть профиль Отправить личное сообщение для 1g0rrr Найти все сообщения от 1g0rrr
  № 1  
Ответить с цитированием
1g0rrr

Регистрация: Jul 2009
Адрес: Донецк
Сообщений: 25
По умолчанию Никак не получается удалить объект

Ситуация:
В моей игре главный герой перемещается постоянно вверх и ему на встречу попадаются монетки, которые он должен собирать. Монетки появляются на экран выше героя, пролетают мимо него, и только вылетев за экран, или попав в героя - удаляются. Так вот, столкнулся с проблемой. Если монеток будет много, штук 20 в секунду, например, то через несколько минут фпс начинает уверенно падать и игра начинает тормозить. Я сначала думал, что обьекты не полностью удаляются, остаются где-то в памяти и тормозят игру. Но выявить это оказывается не так просто.

Моё решение:
Первое что пришло в голову - проверить, удаляет ли Сборщик мусора мой обьект. Для этого я проверил удаление всех ссылок и событий на него, сделал в нём таймер, который раз в секунду делает trace('some text'). И действительно, через секунд 10 после исчезания монетки с экрана - trace - перестаёт выводится, следовательно я посчитал, что обьект удалён сборщиком. Причём, если вызвать сборщик мусора сразу после исчезания монеты с экрана, то trace - тоже сразу же перестаёт выводится, значит обьект по идее точно удаляется с помощью GC. Но тут начались странности.

Странности:
Попробовал специально оставить жесткую ссылку на обьект, присвоив его переменной tmp. Но вопреки моим ожиданиям, после пролёта монеты trace - перестал выводится всёравно, будто обьект удалился. В то же время если вызвать tmp.SomeFunction(), то эта функция успешно выполнится, будто обьект всё еще существует. o_O

Подскажите, как проверить удалён ли обьект из памяти, почему в моём примере были такие странности? Какие инструменты чтобы применять проверить, существует ли обьект в памяти? Как вообще правильно удалять обьект?

Старый 11.10.2011, 22:28
surlac вне форума Посмотреть профиль Отправить личное сообщение для surlac Найти все сообщения от surlac
  № 2  
Ответить с цитированием
surlac
 
Аватар для surlac

блогер
Регистрация: Nov 2010
Сообщений: 143
Записей в блоге: 1
Цитата:
Сообщение от 1g0rrr Посмотреть сообщение
вылетев за экран, или попав в героя - удаляются
Так используйте пул объектов (монеток)! Мало того что Флешу приходится создавать ненужные экземпляры, так Вы его еще заставляете рыскать по дереву (DisplayList) в поисках объекта и удалять его. Монетка доходит до низа/героя - перемещаете её вверх за пределы Stage (y -= stage.width), нужно увеличить размер пула - array.push(new Coin()); иначе array.peek(); (:todo implement peek())

Старый 12.10.2011, 00:12
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 3  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Цитата:
Сообщение от 1g0rrr Посмотреть сообщение
Подскажите, как проверить удалён ли обьект из памяти?
Ну, трейс же вам помог понять, что объект еще в памяти ). А вот как вы, не имея ссылок на удаленный объект, вызвали в нем метод, для меня осталось загадкой.

Сравнивая дампы памяти "во время" и "после" существования объекта. Поможет профилировщик памяти.

Добавлено через 8 минут
Кстати, пока тикает таймер и в нем есть ссылки на обработчики... Объекты, которым принадлежат обработчики будут жить )
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 12.10.2011, 01:06
1g0rrr вне форума Посмотреть профиль Отправить личное сообщение для 1g0rrr Найти все сообщения от 1g0rrr
  № 4  
Ответить с цитированием
1g0rrr

Регистрация: Jul 2009
Адрес: Донецк
Сообщений: 25
Цитата:
Сообщение от surlac Посмотреть сообщение
Так используйте пул объектов (монеток)! Мало того что Флешу приходится создавать ненужные экземпляры, так Вы его еще заставляете рыскать по дереву (DisplayList) в поисках объекта и удалять его. Монетка доходит до низа/героя - перемещаете её вверх за пределы Stage (y -= stage.width), нужно увеличить размер пула - array.push(new Coin()); иначе array.peek(); (:todo implement peek())
Мне кажется, что пул - это некрасивая и неправильная архитектура. Ведь логичнее же создать монетку, а потом её просто удалить. Оставлю этот вариант на конец, если ничего не поможет - тогда прийдётся пул делать.

Добавлено через 4 минуты
Цитата:
Сообщение от dimarik Посмотреть сообщение
Ну, трейс же вам помог понять, что объект еще в памяти ). А вот как вы, не имея ссылок на удаленный объект, вызвали в нем метод, для меня осталось загадкой.

Сравнивая дампы памяти "во время" и "после" существования объекта. Поможет профилировщик памяти.

Добавлено через 8 минут
Кстати, пока тикает таймер и в нем есть ссылки на обработчики... Объекты, которым принадлежат обработчики будут жить )
Таймер я использовал с параметром weakReference, поэтому он удалялся. В том-то и дело, что таймер тикать переставал, тоесть трейс говорил, что обьект удалён, хотя ссылка на него у меня одна оставалась. По ней и обращался. Пользуюсь Flash Develop, там только дебагер есть, который мало мне помог.. Какие есть еще профилировщики?

Старый 12.10.2011, 02:41
crazyone вне форума Посмотреть профиль Отправить личное сообщение для crazyone Найти все сообщения от crazyone
  № 5  
Ответить с цитированием
crazyone
 
Аватар для crazyone

блогер
Регистрация: Nov 2007
Адрес: Киев
Сообщений: 557
Записей в блоге: 2
Когда-то давно, когда у меня были такие же проблемы, я написал для этого класс, который позволял бы считать количество отслеживаемых элементов в памяти, записывая их в Dictionary со слабыми ключами (weakKeys):
Код AS3:
package com.doctorstal.data{
	import flash.events.TimerEvent;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
 
	public class MemChecker{
		private static var _dArr=new Array();
		private static var _timer:Timer;
 
		private static var _inited:Boolean=false;
 
		private static function init(){
			if(!_inited){
				_inited=true;
				_timer=new Timer(2000);
				_timer.addEventListener(TimerEvent.TIMER,timerTickHandler);
				_timer.start();
			}
		}
 
		public static function addItem(obj:Object,key:String="undef"){
			init();
			var _d:Dictionary;
			if(!(_dArr[key] is Dictionary)){
				_d=new Dictionary(true);
				_dArr[key]=_d;
			}else{
				_d=_dArr[key];
			}
			_d[obj]={};
		}
		public static function getItemCount(key:String):uint{
			var _d=_dArr[key];
			if(!(_d is Dictionary)) return 0;
			var obj:Object;
			var count=0;
			for(obj in _d){
				count++;
			}
			return count;
		}
		private static function timerTickHandler(e:TimerEvent){
			for(var i in _dArr){
				trace("MemChecker: \""+i+"\":"+getItemCount(i)+" items.");
			}
		}
	}
}
При создании объекта вызывалось
Код AS3:
MemChecker.addItem(object);
и каждые 2 секунды выводился трейс с количеством неудаленных из памяти объектов, которые регистрировались. Можно, конечно, и весь список вывести, но зачем?

Старый 12.10.2011, 23:31
1g0rrr вне форума Посмотреть профиль Отправить личное сообщение для 1g0rrr Найти все сообщения от 1g0rrr
  № 6  
Ответить с цитированием
1g0rrr

Регистрация: Jul 2009
Адрес: Донецк
Сообщений: 25
Спасибо за помощь. Продвинулся немного. Обьект уже получается удалить. Оказывается если поставить листенер c weakReference=true, и оставить ссылку на обьект, то при проходе GC этот листенер слетает, а обьект остаётся нетронутым. Если же делать weakReference=false, то листенер не даст удалить обьект, даже если на него нет других ссылок.
Но оказывается в Flash Develop-e есть неплохой встроеный профайлер, который показывает все переменные и занимаемую ими память.
Теперь я столкнулся теперь с другой проблемой. В каждом обьекте у меня есть еще обьект b2body из box2d библиотеки. Так вот удаляю этот обьект как по инструкции worldLink.DestroyBody(bodyLink); проверяю worldLink.GetBodyCount() - количество уменьшилось на один. В то же время профайлер показывает, что обьект остался в памяти даже после прохода GC. Пересматривал много раз, вроде ссылок на него больше нет, поэтому должен удалиться.. И опять у меня ступор. =/

Старый 13.10.2011, 07:51
goodguy вне форума Посмотреть профиль Найти все сообщения от goodguy
  № 7  
Ответить с цитированием
goodguy
Banned
[+1 05.11.11]
[+1 09.08.11]

Регистрация: Jan 2010
Адрес: РФ. Кемеровская область
Сообщений: 3,243
Цитата:
перемещаете её вверх за пределы Stage (y -= stage.width)
Крутяк ) Уж тогда логичнее
Код AS3:
y -= stage.stageHeight;
Цитата:
В то же время профайлер показывает, что обьект остался в памяти даже после прохода GC. Пересматривал много раз, вроде ссылок на него больше нет, поэтому должен удалиться.. И опять у меня ступор. =/
Он не удалится из памяти сам. Его снесет сборщик мусора, когда посчитает это нужным.
А тела бокс2д жрут мало памяти, соответственно и рассматриваются GC позже более "ресурсоемких" объектов

Создать новую тему Ответ Часовой пояс GMT +4, время: 21:51.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Теги
gc , обьект , удаление

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 21:51.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.