|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Регистрация: Oct 2016
Сообщений: 2
|
Почему наследник BitmapData не диспозит себя до конца?
Почему наследник BitmapData не диспозит себя до конца?
Вывод этот я сделал из следующего теста, итак: 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; } } public class BitmapDataExtended extends BitmapData { public function BitmapDataExtended(width:int, height:int, transparent:Boolean, fillColor:uint) { super(width, height, transparent, fillColor); } } 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. |
|
|||||
Modus ponens
|
Это не более чем догадка.
Я не знаю что именно показывает System.privateMemory. но, как правило, нет смысла ожидать от аллокатора, что он будет удалять / выделять именно столько памяти, сколько нужно для создания объекта видимого пользователю. Так это потому, что память обычно выделяется страницами. Разные аллокаторы по-разному это делают. По-разному ищут свободные места, могут переставлять объеткты в памяти местами для оптимизации и т.д. Без точного понимания того, что делает аллокатор - информация о том, сколько памяти было выделено не особо полезна. Более того, от чего-то типа Флеша я бы не стал ожидать очень экономного выделения памяти, особенно, если ее у пользователя вполне еще много свободной. Т.е. такого теста не достаточно для каких-либо заключений. Нужно попробовать создавать объекты разного размера, много раз, желательно при этом следить за системными вызовами, и иметь под рукой виртуальную машину, где можно настроить объем памяти: чтобы увидеть как Флеш себя ведет, когда памяти мало, например. Ну или требовать у Адоба нормальной документации / открыть исходники
__________________
Hell is the possibility of sanity |
|
|||||
Регистрация: Oct 2016
Сообщений: 2
|
Прайват мемори отражает потребление памяти приложением,
значения её близки к тому что показывает диспечер задач, так что думаю нет причин ей не доверять. По поводу нескольких замеров вы правы, если запустить тест в цикле, через несколько итераций ситуация нормализуется, количество выделяемой и освобождаемой памяти становиться одинаковым, а общее потребление по сравнению с первыми итерациями снижается. Немного отходя от начальной темы, я начал эти копания не от хорошей жизни, приложение генерящие растр, при работе с достаточно большими картинками, либо не может создать очередной инстанс битмепдаты, и это полбеды, можно что-то неиспользуемое свопнуть на диск, либо просто умирает, выдавая в консоль скупое [Выгрузка SWF]. При этом судя по прайват мемори памяти ещё много. Сходный тест создающий битмепдаты аналогичных размеров дохнет на полутора гигах, а приложение на половинке. Есть ли идеи, что может быть этому причиной? |
|
|||||
Modus ponens
|
А что такое "потребление памяти приложением"?
- Это вся память выделенная ядром процессу приложения? - Это вся память которую код приложения чем-нибудь заполнил? - Это вся память выделенная ядром процессу приложения, учитывая неиспользованые участки выделенных страниц? И т.д. По поводу почему приложение умирает: Однозначный ответ может быть только у Адобовских разработчиков. Кроме них никто не знает как работает флешевый аллокатор. Но если строить догадки: у флешевой виртуальной машины должен быть свой аллокатор. Для него используется какая-нибудь структура данных, типа той же кучи. У нее могут быть определенные ограничения на аддресацию. Т.е, например, при достижении 1.5 Гб памяти в куче нужно сделать реаллокацию т.как она достигла предельного заполнения. Если это обычная куча, то каждая такая реаллокация увеличивает ее в два раза. Ну и возможно система просто не готова выделить 3 Гб памяти. Ну и, возможно, что аллокатор флеша не допускает работы со свопом (потому что так проще жить). Когда-то давно мне на глаза попадался документ о граничных значениях для разных параметров флешевой виртуальной машины. Возможно, если поискать, там будет описано сколько памяти может выделить одна машина.
__________________
Hell is the possibility of sanity |
|
|||||
Регистрация: Oct 2006
Сообщений: 2,281
|
Цитата:
|
|
|||||
Modus ponens
|
Я не знаю как в Виндовсе оно работает. В Линуксе можно mlock использовать - тогда гарантировано память будет выделятся только физическая, а не виртуальная. Скорее всего в Виндовсе что-то похожее тоже есть.
Но я не знаю, использует Флеш своп или нет. Это было просто предположение. Ну и, например, в риалтайм системах принято писать аллокаторы самим, и там уже обычно свои погремушки, кто сколько, как и зачем памяти выделяет будет зависеть от конкретного аллокатора. Флеш, конечно, не РТ система, но наверняка там свой аллокатор.
__________________
Hell is the possibility of sanity |
|
|||||
.
|
Цитата:
Сцылка на BitmapData (bd) помирает при выходе из конструктора. А gc должен бы, по-хорошему, подобрать за тем, что не имеет GCRoot. И да, это точно лишнее |
|
|||||
Регистрация: Mar 2007
Сообщений: 319
|
Да все там понятно как работает, как и везде
https://github.com/nxmirrors/tamarin...Utils.cpp#L223 https://github.com/nxmirrors/tamarin...Utils.cpp#L132 И мерить память в момент запуска не следует 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("----"); } } Ответ на вопрос что собственно показывает 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/ По поводу памяти занимаемой изображением Если у тебя приложение работает с загружаемыми картинками, то нужно понимать что в памяти хранятся не пиксели (как принято думать), а пиксели + сжатое изображение + выделяется память в момент разжатия Например тест: 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")); Догадливый человек скажет, что есть же ImageDecodingPolicy var context:LoaderContext = new LoaderContext(); context.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD; Если хочешь избавиться от этого эффекта, то нужно загруженную bitmapData скопировать попиксельно (не клонировать), а loader'у сделать unload. Тогда у тебя будет бОльший контроль над выделяемой памятью и поведение будет более предсказуемым. 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. |
|
|||||
Цитата:
Это не лишнее, если нужно сразу освободить память, о чем прямо сказано в доках
__________________
Ко мне можно и нужно обращаться на ты) |
|
|||||
.
|
Вообще какая разница должна быть, что память где-то там должна освободиться? Совершенно не должно волновать. Ссылку потёр и радуйся жизни. Остальное должна сделать среда. А если она не умеет это делать, то зачем она называется системой с автоматическим управлением памятью? А так получается, что ну, типа ты можешь и сам взять на себя управление памятью. А зачем? Ну, типа мы не можем гарантировать освобождение. Так что ли это выглядит?
|
Часовой пояс GMT +4, время: 15:13. |
|
« Предыдущая тема | Следующая тема » |
|
|