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

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

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

Регистрация: Oct 2016
Сообщений: 2
Question Почему наследник BitmapData не диспозит себя до конца?

Почему наследник BitmapData не диспозит себя до конца?
Вывод этот я сделал из следующего теста, итак:
Код AS1/AS2:
public class DisposeTest extends Sprite
{
	private var memory:int;
 
	public function DisposeTest()
	{
		memory = System.privateMemory;
		var bd:BitmapData = new BitmapData(2000,2000,true,0x0);
		trackMemory(); //  16003072
		bd.dispose();   
		bd = null;        
		trackMemory(); // -16003072
	}
 
	private function trackMemory():void
	{
		var currentMemory:int = System.privateMemory;
		trace (currentMemory - memory);
		memory = currentMemory;
	}
}
Пока всё работает как часы, но если заменить битмепдату на наследника, например такого
Код AS1/AS2:
public class BitmapDataExtended extends BitmapData
{
	public function BitmapDataExtended(width:int, height:int, transparent:Boolean, fillColor:uint)
	{
		super(width, height, transparent, fillColor);
	}
}
Тест будет вести себя по другому:
Код AS1/AS2:
public function DisposeTest()
{
	memory = System.privateMemory;
	var bd:BitmapData = new BitmapDataExtended(2000,2000,true,0x0);
	trackMemory();	 // 16072704
	bd.dispose();
	bd = null;
	trackMemory();   // -16003072
}
То есть во втором случае, памяти выделяется больше, а освобождается как в первый раз.
Хотелось бы понять почему так происходит, и как этого избежать.


Последний раз редактировалось also; 16.10.2016 в 00:03.
Старый 16.10.2016, 00:19
wvxvw вне форума Посмотреть профиль Отправить личное сообщение для wvxvw Найти все сообщения от wvxvw
  № 2  
Ответить с цитированием
wvxvw
Modus ponens
 
Аватар для wvxvw

модератор форума
Регистрация: Jul 2006
Адрес: #1=(list #1#)
Сообщений: 8,049
Записей в блоге: 38
Это не более чем догадка.

Я не знаю что именно показывает System.privateMemory. но, как правило, нет смысла ожидать от аллокатора, что он будет удалять / выделять именно столько памяти, сколько нужно для создания объекта видимого пользователю. Так это потому, что память обычно выделяется страницами. Разные аллокаторы по-разному это делают. По-разному ищут свободные места, могут переставлять объеткты в памяти местами для оптимизации и т.д. Без точного понимания того, что делает аллокатор - информация о том, сколько памяти было выделено не особо полезна. Более того, от чего-то типа Флеша я бы не стал ожидать очень экономного выделения памяти, особенно, если ее у пользователя вполне еще много свободной.
Т.е. такого теста не достаточно для каких-либо заключений. Нужно попробовать создавать объекты разного размера, много раз, желательно при этом следить за системными вызовами, и иметь под рукой виртуальную машину, где можно настроить объем памяти: чтобы увидеть как Флеш себя ведет, когда памяти мало, например.
Ну или требовать у Адоба нормальной документации / открыть исходники
__________________
Hell is the possibility of sanity

Старый 16.10.2016, 14:03
also вне форума Посмотреть профиль Отправить личное сообщение для also Найти все сообщения от also
  № 3  
Ответить с цитированием
also

Регистрация: Oct 2016
Сообщений: 2
Прайват мемори отражает потребление памяти приложением,
значения её близки к тому что показывает диспечер задач,
так что думаю нет причин ей не доверять.

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

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

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

Есть ли идеи, что может быть этому причиной?

Старый 17.10.2016, 16:43
wvxvw вне форума Посмотреть профиль Отправить личное сообщение для wvxvw Найти все сообщения от wvxvw
  № 4  
Ответить с цитированием
wvxvw
Modus ponens
 
Аватар для wvxvw

модератор форума
Регистрация: Jul 2006
Адрес: #1=(list #1#)
Сообщений: 8,049
Записей в блоге: 38
А что такое "потребление памяти приложением"?
- Это вся память выделенная ядром процессу приложения?
- Это вся память которую код приложения чем-нибудь заполнил?
- Это вся память выделенная ядром процессу приложения, учитывая неиспользованые участки выделенных страниц?
И т.д.

По поводу почему приложение умирает:
Однозначный ответ может быть только у Адобовских разработчиков. Кроме них никто не знает как работает флешевый аллокатор. Но если строить догадки: у флешевой виртуальной машины должен быть свой аллокатор. Для него используется какая-нибудь структура данных, типа той же кучи. У нее могут быть определенные ограничения на аддресацию. Т.е, например, при достижении 1.5 Гб памяти в куче нужно сделать реаллокацию т.как она достигла предельного заполнения. Если это обычная куча, то каждая такая реаллокация увеличивает ее в два раза. Ну и возможно система просто не готова выделить 3 Гб памяти. Ну и, возможно, что аллокатор флеша не допускает работы со свопом (потому что так проще жить).

Когда-то давно мне на глаза попадался документ о граничных значениях для разных параметров флешевой виртуальной машины. Возможно, если поискать, там будет описано сколько памяти может выделить одна машина.
__________________
Hell is the possibility of sanity

Старый 17.10.2016, 21:00
undefined вне форума Посмотреть профиль Отправить личное сообщение для undefined Найти все сообщения от undefined
  № 5  
Ответить с цитированием
undefined

Регистрация: Oct 2006
Сообщений: 2,281
Цитата:
Ну и, возможно, что аллокатор флеша не допускает работы со свопом (потому что так проще жить).
а это разве не головная боль оси?

Старый 17.10.2016, 21:53
wvxvw вне форума Посмотреть профиль Отправить личное сообщение для wvxvw Найти все сообщения от wvxvw
  № 6  
Ответить с цитированием
wvxvw
Modus ponens
 
Аватар для wvxvw

модератор форума
Регистрация: Jul 2006
Адрес: #1=(list #1#)
Сообщений: 8,049
Записей в блоге: 38
Я не знаю как в Виндовсе оно работает. В Линуксе можно mlock использовать - тогда гарантировано память будет выделятся только физическая, а не виртуальная. Скорее всего в Виндовсе что-то похожее тоже есть.

Но я не знаю, использует Флеш своп или нет. Это было просто предположение.
Ну и, например, в риалтайм системах принято писать аллокаторы самим, и там уже обычно свои погремушки, кто сколько, как и зачем памяти выделяет будет зависеть от конкретного аллокатора. Флеш, конечно, не РТ система, но наверняка там свой аллокатор.
__________________
Hell is the possibility of sanity

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

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Цитата:
Код AS3:
public function DisposeTest() {
	var bd:BitmapData = new BitmapData(2000, 2000, true, 0x00000000);
	bd.dispose();
	bd = null;
}
А вы не находите, что это лишнее?
Код AS3:
bd.dispose();
Сцылка на BitmapData (bd) помирает при выходе из конструктора. А gc должен бы, по-хорошему, подобрать за тем, что не имеет GCRoot.
И да, это точно лишнее
Код AS3:
bd = null;
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

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

Регистрация: Mar 2007
Сообщений: 319
Да все там понятно как работает, как и везде
https://github.com/nxmirrors/tamarin...Utils.cpp#L223
https://github.com/nxmirrors/tamarin...Utils.cpp#L132

И мерить память в момент запуска не следует
Код AS3:
	public class DisposeTest extends Sprite
	{
		public function DisposeTest()
		{
			super();
			stage.addEventListener(MouseEvent.CLICK, onClick);
		}
 
		private function onClick(event:MouseEvent):void
		{
			var memory:int = System.privateMemory;
			var bd:BitmapDataExtended = new BitmapDataExtended(2000,2000,true,0x0);
			trace((-memory + (memory = System.privateMemory))); //16003072
			bd.dispose();
			bd = null;
			System.gc();
			trace((-memory + (memory = System.privateMemory))); //-16003072
			trace("----");
		}
	}
В конструкторе приложения нельзя мерить память, так как эта та точка вызова as кода когда еще окно не создалось, контекст рендера не инициализировался, возможно даже буфер на trace не выделился, и значения в первом случае с BitmapData тоже будут с долей вероятности разные, попробуй первый вариант запускать раз 20 подряд

Ответ на вопрос что собственно показывает System.privateMemory https://github.com/nxmirrors/tamarin...Class.cpp#L215 https://github.com/nxmirrors/tamarin...rtWin.cpp#L188
На почитать http://msdn.microsoft.com/en-us/library/bb331824.aspx https://habrahabr.ru/post/202242/

По поводу памяти занимаемой изображением
Если у тебя приложение работает с загружаемыми картинками, то нужно понимать что в памяти хранятся не пиксели (как принято думать), а пиксели + сжатое изображение + выделяется память в момент разжатия
Например тест:
Код AS3:
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (event:Event):void
			{
				var bitmap:Bitmap = Bitmap(loader.contentLoaderInfo.content);
				trace("Предполагаемая занимаемая память:", bitmap.bitmapData.width * bitmap.bitmapData.height * 4); //5615780
				var memory:int = System.privateMemory;
				var color:uint = bitmap.bitmapData.getPixel32(0, 0);
				trace("Выделенная память после чтения:", (-memory + (memory = System.privateMemory))); //11239424
				bitmap.bitmapData.dispose();
				trace("Освободившаяся память после уничтожения:", (memory - (memory = System.privateMemory))); //5619712
			});
			loader.load(new URLRequest("http://www.freeiconspng.com/uploads/superman-logo-png-4.jpeg"));
Нужно помнить, что как только ты попытаешься считать/отрисовать/поместить на экран данные из bitmapData изображение будет разжато в пиксели и будет выделено больше памяти для декодера (примерно в два раза больше чем само изображение), и соответственно память освободится если перестанешь читать после вызова сборки. Флеш это делает для экономии памяти в случае если изображение уже не используется, но может быть использовано так как ссылка на него осталась.

Догадливый человек скажет, что есть же ImageDecodingPolicy
Код AS3:
var context:LoaderContext = new LoaderContext();
context.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD;
Но после первого цикла чтения и отработки сборки, поведение будет таким же как и при ON_DEMAND

Если хочешь избавиться от этого эффекта, то нужно загруженную bitmapData скопировать попиксельно (не клонировать), а loader'у сделать unload. Тогда у тебя будет бОльший контроль над выделяемой памятью и поведение будет более предсказуемым.
Код AS3:
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (event:Event):void
			{
				var bitmapData:BitmapData = Bitmap(loader.contentLoaderInfo.content).bitmapData;
				var newBitmapData:BitmapData = new BitmapData(bitmapData.width, bitmapData.height, bitmapData.transparent, 0x0);
				for (var x:int = 0; x < bitmapData.width; x++) 
				{
					for (var y:int = 0; y < bitmapData.width; y++) 
					{
						if (bitmapData.transparent)
						{
							newBitmapData.setPixel32(x, y, bitmapData.getPixel32(x, y));
						}
						else
						{
							newBitmapData.setPixel(x, y, bitmapData.getPixel(x, y));
						}
					}
				}
				bitmapData.dispose();
				loader.unloadAndStop(true);
 
				//Далее использовать только newBitmapData
			});
			loader.load(new URLRequest("http://www.freeiconspng.com/uploads/superman-logo-png-4.jpeg"));


Последний раз редактировалось Nooob; 03.11.2016 в 04:04.
Старый 03.11.2016, 05:57
caseyryan вне форума Посмотреть профиль Отправить личное сообщение для caseyryan Найти все сообщения от caseyryan
  № 9  
Ответить с цитированием
caseyryan
 
Аватар для caseyryan

Регистрация: Jun 2012
Адрес: Новосибирск
Сообщений: 6,644
Записей в блоге: 4
Цитата:
А вы не находите, что это лишнее?
Противник диспозов детектэд)

Это не лишнее, если нужно сразу освободить память, о чем прямо сказано в доках
__________________
Ко мне можно и нужно обращаться на ты)

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

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Вообще какая разница должна быть, что память где-то там должна освободиться? Совершенно не должно волновать. Ссылку потёр и радуйся жизни. Остальное должна сделать среда. А если она не умеет это делать, то зачем она называется системой с автоматическим управлением памятью? А так получается, что ну, типа ты можешь и сам взять на себя управление памятью. А зачем? Ну, типа мы не можем гарантировать освобождение. Так что ли это выглядит?
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

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

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

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


 


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


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