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

Вернуться   Форум Flasher.ru > Блоги > dimarik

Оценить эту запись

Немного о Vector и ByteArray

Запись от dimarik размещена 28.03.2014 в 22:48
Обновил(-а) dimarik 01.04.2014 в 12:35

Как всегда, буду краток.

Код AS3:
const someVector:Vector.<SomeT> = new <SomeT>[];
... добавляем объекты SomeT в someVector
someVector.length = 0; // ! освобождения памяти не происходит !
// Память может только расти. Освободить память можно лишь 
someVector = null;
Текущая версия Adobe Scout помещает эту память в категорию Uncategorized.

ByteArray освобождает память только по clear(), установка его length = 0 не освобождает память.

UPD
Вот листинг программы теста вектора. Собиралось AIR SDK 4.0.0.1628 c -advanced-telemetry. Упаковывалось под iOS, тестировалось на iPhone 4S.

Код AS3:
package
{
 
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.system.System;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;
 
 
[SWF(width="960", height="640", frameRate="60", backgroundColor="#005686")]
 
public class VectorMemoryAllocationTest extends Sprite
{
 
	//-------------------------------------------------------------------------
	//
	//   Constructor
	//
	//-------------------------------------------------------------------------
 
	/**
	 * Constructor
	 */
	public function VectorMemoryAllocationTest() {
		super();
		this._taps = 0;
		Multitouch.inputMode = MultitouchInputMode.NONE;
		super.stage.frameRate = 10;
		super.stage.addEventListener(MouseEvent.MOUSE_DOWN, this.handler_interaction);
	}
 
	private var _taps:		int;
 
	private var _vector:	Vector.<uint>;
 
	private function handler_interaction(event:Event):void {
		switch (this._taps) {
			case 0:
				trace('Create vector');
				this._vector = new <uint>[];
				System.gc();
				break;
 
			case 1:
				trace('Set vector length');
				this._vector.length = 1024 * 1024;
				break;
 
			case 2:
				trace('Splice vector');
				this._vector.splice(0, this._vector.length);
				break;
 
			case 3:
				trace('gc()');
				System.gc();
				break;
 
			case 4:
				trace('Null vector');
				this._vector = null;
				break;
 
			default:
				this._taps = -1;
		}
 
		this._taps++;
	}
 
}
}
Вот скриншот лога AdobeScout


Вот сам лог
Миниатюры
Нажмите на изображение для увеличения
Название: VectorMemoryAllocationTest_comment.png
Просмотров: 1377
Размер:	40.4 Кб
ID:	414  
Вложения
Тип файла: rar VectorMemoryAllocationTest.rar (15.5 Кб, 458 просмотров)
Всего комментариев 44

Комментарии

Старый 29.03.2014 02:57 Babylon вне форума
Babylon
 
Аватар для Babylon
И о чем это говорит? Что Vector хоть и упакованный массив, но не массив?
Старый 29.03.2014 21:39 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
Для верности, думаю, стоит дополнить информацией по такому кейсу:
- создаем ByteArray длиной N
- наполняем его
- ставим длину на 0
- ставим длину на M
- снова наполняем его
Старый 30.03.2014 13:12 toFL вне форума
toFL
Цитата:
установка его length = 0 не освобождает память
Так это логично, он же выделил кусок для тебя. Если бы по каждому чиху он занимался перераспределением памяти, было бы хуже.
Старый 30.03.2014 18:50 alatar вне форума
alatar
 
Аватар для alatar
Цитата:
ByteArray освобождает память только по clear(), установка его length = 0 не освобождает память.
Вообще это странно, судя по коду на tamari-redux там вообще новый массив создается при уменьшении длины. Может просто heap не уменьшается? Или память растет, если в уменьшенный массив начать писать данные?
Старый 30.03.2014 19:11 Babylon вне форума
Babylon
 
Аватар для Babylon
а хип то по-моему должен как раз увеличиваться
Старый 31.03.2014 11:34 toFL вне форума
toFL
Цитата:
Если длина установлена в значение, превышающее текущую длину, правая часть массива байтов заполняется нулями.
Если длина установлена в значение, меньшее текущей длины, выполняется усечение массива байтов.
В чем суть проблемы то? ByteArray при нехватке памяти резервирует в 1,999... (стремится к 2) раз больше чем у него есть сейчас. Никто не заявляет что он должен по "length=0" освобождать что либо.
Старый 31.03.2014 12:35 alexcon314 вне форума
alexcon314
Имхо length вообще должна быть read only. Ибо путаница и разброд в умах.
Старый 31.03.2014 13:59 Babylon вне форума
Babylon
 
Аватар для Babylon
Разброда нет - есть желание повторно использовать область памяти.
Старый 31.03.2014 14:06 alexcon314 вне форума
alexcon314
Используйте, что мешает? Только длину не трогайте.
Старый 31.03.2014 14:19 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Цитата:
// Освобождения памяти не происходит!
// Память может только расти.
Это же прекрасно. Уменьшил length — и все, кто обращается к этому вектору знают, сколько элементов "в работе" в данный момент времени. И не страшно, что "хвостик" остался, ведь в следующем шаге он, возможно, будет использован… а может и его мало будет — тогда и увеличим память под вектор.

На практике. Вид, скажем, запрашивает у модели не свойство, а какой-то массив, который всегда разный. Ну например, по горячему, в match 3 всегда разное количество ячеек складывается. Конечно можно каждый раз пересоздавать массив в модели уничтожая его с помощью length=0, но это же не кошерно! Мы же тут все ратуем за пулы и прочие экономные ходы! Значит лучше не пересоздавать, а просто указывать (в отдельной переменной) что, мол, массив большой, но ты бери только первые N элементов. Да. А тут прелесть какая — можно просто взять length и все — он всегда указывает сколько элементов взять. При этом и вектор не пересоздается, и дополнительных переменных не нужно.

Вот бы и в массиве так!
Старый 31.03.2014 14:46 alexcon314 вне форума
alexcon314
Чего-то я не понял, речь идет о том, что при указании (принудительном) длины, массив (ByteArray) все равно пересозадется, не? Зависит от мгновенных условий, возможно, да. Но вообще просто так прикрутить однажды оторвавшийся хвостик обратно, частично, целиком или с довеском - операция весьма нетривиальная, если конечно не держать в памяти все и вся вечно в состоянии "прибито гвоздями".
Я думаю, что "хвостики" могут быть оправданы на памяти, выделенной в пределах одной страницы (4096 байт). Но не факт.
Старый 31.03.2014 14:53 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Оправдывать удержание хвостика в памяти доверим программисту… разумеется, ограничив его аппетиты каким-то достаточно высоким потолком.

Насчет "прикрутить" — ничего прикручивать не нужно, по крайней мере в BA. Ничего ведь и не откручивается, мы просто указываем текущий размер массива, дальше которого считывать данные нельзя.
Старый 31.03.2014 15:07 alexcon314 вне форума
alexcon314
Я всего лишь выражаю сомнение в том факте, что принудительное указание length безусловно сохраняет текущее распределение памяти как есть. Из чисто логических соображений, это не так. Т.е. откручивание/прикручивание таки происходит . А стало быть, практически данная операция несет в себе больше вопросов "что на самом деле происходит", чем увернности "да, все происходит именно так, как я думаю должно происходить". Программисту тут далеко не все доверяется, увы (ура, нужное подчеркнуть).
Потом, что ты так цепляешься: "вот в одном месте установили length, все сразу будут знать, до какого байта читать". length read only не исключает же, что все будут ее знать, не?
Обновил(-а) alexcon314 31.03.2014 в 15:20
Старый 31.03.2014 16:19 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Цитата:
length read only не исключает же, что все будут ее знать, не?
Не ) именно потому что read-only, а хочется read-write но без реструктуризации в случае уменьшения.
Старый 31.03.2014 16:34 alexcon314 вне форума
alexcon314
Ну, так читай-пиши, можно же . Мое имхо - это только мое имхо.
Но раз уж так хочется без реструктуризации в случае уменьшения - нужно ввести, например capacity какой-нибудь (read-write), т.е. число элементов, которые может вместить массив, прежде чем потребуется изменить его размер. Тогда на одном массиве можно безболезненно регулировать "длину" как душе угодно, пока не выбьешься за capacity.
Отделить мух от котлет: длина - это длина, размер - это размер. См. List из C#.
Старый 31.03.2014 16:37 etc вне форума
etc
 
Аватар для etc
splice-то хоть работает?
Старый 31.03.2014 17:03 alexcon314 вне форума
alexcon314
Кстати, да.
Цитата:
splice - Этот метод изменяет массив, не создавая копии.
Работает, только наверно медленно, как утюг.
Старый 01.04.2014 12:22 dimarik вне форума
dimarik
 
Аватар для dimarik
Цитата:
splice-то хоть работает?
Не работает. Я обновил пост.
Старый 02.04.2014 11:47 alexcon314 вне форума
alexcon314
Вроде как, splice() должен выделять память под удаляемые элементы, не? Если удалять все, то даш на даш выходит.
Старый 02.04.2014 15:00 dimarik вне форума
dimarik
 
Аватар для dimarik
Зайду с другого краю. Как очистить память, занимаемую элементами вектора и более не нужными, не разрушая его?
Старый 02.04.2014 17:09 Babylon вне форума
Babylon
 
Аватар для Babylon
Сколько памяти занимает один элемент вектора и как ее занулить?
Старый 02.04.2014 21:34 alexcon314 вне форума
alexcon314
Почему бы просто не занулять элементы (=null)? uint, int обнулится (=0), а ссылочный тип соберется gc, при этом элемент-ссылка в векторе останется на месте, только за-null'енная. Этого ты добиваешься? Вот только память из под вектора так не высвободишь, нули тоже место занимают, но ведь уже не о том речь?
Обновил(-а) alexcon314 02.04.2014 в 21:56
Старый 02.04.2014 21:49 Babylon вне форума
Babylon
 
Аватар для Babylon
Я бы так и сделал перед переустановкой длины, но не факт, что сработает.
Старый 02.04.2014 22:11 Babylon вне форума
Babylon
 
Аватар для Babylon
Память выделяется если элемент не помещается. Если элемент незанулен она и не освободится. Изменение длины на это не влияет. Изменение длины влияет на доступность индекса. В противном случает выскочит ошибка.
Старый 03.04.2014 01:27 toFL вне форума
toFL
Рас уж волнуетесь о потреблении памяти, то не забудьте проверить XML. Это очень тяжелый класс и при работе с ним выделяется огромное кол-во памяти, которое впрочем чистится в следующем кадре. Если кому интересно, могу написать об этом поподробнее.
Старый 03.04.2014 01:41 Babylon вне форума
Babylon
 
Аватар для Babylon
Мне интересно.
Старый 03.04.2014 08:54 alexcon314 вне форума
alexcon314
Интересное чтиво (про векторы и массивы).
Старый 03.04.2014 15:46 toFL вне форума
toFL
Цитата:
Мне интересно.
Написал в блог тему "ОЗУ и XML", должна скоро добавиться.
Старый 03.04.2014 18:29 Babylon вне форума
Babylon
 
Аватар для Babylon
Интересное чтиво (про векторы и массивы и хеши)
Старый 03.04.2014 23:00 dimarik вне форума
dimarik
 
Аватар для dimarik
В общем, если увидите в коде vector.length = 0, то знайте, что автор не читал чтиво.
Старый 03.04.2014 23:12 Babylon вне форума
Babylon
 
Аватар для Babylon
dimarik, ну и резюме твоё? Нужно пересоздавать новый вектор? Я видел такие советы в интернете.
Старый 03.04.2014 23:18 dimarik вне форума
dimarik
 
Аватар для dimarik
Да, судя по чтиву jpauclair, он настоятельно рекомендует не заниматься ерундой, а создавать новый вектор и копировать туда часть необходимых данных из прежнего, если требуется их оставить. А старый вектор занулять. Этому челу я доверяю, кстати.
Старый 04.04.2014 10:40 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
С этим может быть проблема, если кто-то хранит прямую ссылку на этот вектор. И это, в общем-то, нормально.
Старый 22.04.2014 22:56 dimarik вне форума
dimarik
 
Аватар для dimarik
Вроде бы не очень нормально. Память растет как на дрожжах. Лучше бы чистить научились уже неиспользуемое пространство. А так получается патовая ситуация. Я храню ссылки на детей а ля Composite Pattern. Дети приходят и уходят. Дети детей приходят и уходят. А вектора наши, кхм, только растут и нет предела этим ростам. Я вот в двигле Starling постоянно наблюдаю сцену из кинокомедии: занули память вектору через его длину. А если смотреть на фарс со статическими векторами, то вообще истерия берет. Уже даже не смешно нифига.
Старый 23.04.2014 12:39 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Нормально - в смысле, занулять вектор, как делает господин jpauclair.
Старый 25.04.2014 18:42 expl вне форума
expl
Цитата:
Вроде бы не очень нормально. Память растет как на дрожжах. Лучше бы чистить научились уже неиспользуемое пространство
Ну если нативная реализация списка не устраивает, можно сделать свою версию
(для as3 - с диким оверхедом, но если важна память - почему нет?)

Берём и создаём класс, в котором делаем ссылку на Vector
Если размер уменьшается в 2 раза от максимального, создаём новый, короткий, копируем туда значения предыдущего, ссылку на предыдущий зануляем

Если уже совсем загнаться, забыть что Vector умеет менять размер и захотеть переиспользовать память, то список можно организовать следующим образом:

- Надо увеличить емкость списка - старый вектор кидаем в пул, новый, в 2 раза больше - достаём из пула
или создаём, копируя значения с предыдущего вектора

- Размер стал меньше емкости в 4 раза(не в 2! - в 2 раза мы увеличиваем, а то будем ради одного элемента туда-сюда блоки по 100500 элементов гонять) - кидаем обратно в пул, достаём поменьше, копируем в него значения

И конечно, надо либо забыть про типизацию, либо написать по реализации на каждый тип - генериков нет
Не для as3, конечно, такие забавы
Старый 25.04.2014 19:43 toFL вне форума
toFL
А что с Array? Тоже самое или такой проблемы нет?
Старый 26.04.2014 00:13 alexcon314 вне форума
alexcon314
Дилемма "длина"-"размер" продолжает будоражить умы?
Судя по первой части чтива, в основе Array сидит, тот же dense array, что и в векторе. Почему там что-то должно быть иначе? Управлять памятью "а-ля Си", ну никак...

Кстати, о пулах.. Было бы неплохо делать массивы с размером, кратным 4К , тем более, что меньше он все равно быть не может. Инициализировать до кучи и использовать по полной. И забыть про то, что length is read-write после инициализации. Тогда есть неплохой шанс сильно облегчить работу менеджеру памяти в плане очистки-выделения хотя бы.

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

Оффтопом вспомнилось, был у меня трейсер-дампер простенький запилен для проектора, воочию убедился в том, что при указании длины ByteArray он физически помещается в другой блок памяти, старый остается не у дел (при length=0 точно, на других значениях не помню, но все шансы за то). Воочию же видел, что new ByteArray() выделяет сразу блок 4096 байт памяти, не всегда чистой, кстати, блуд в идиотизмах писал.

UPD. Написал 4К для винды, как там в мобилах не скажу точно..
Обновил(-а) alexcon314 26.04.2014 в 00:31
Старый 26.04.2014 00:19 in4core вне форума
in4core
 
Аватар для in4core
dimarik - гляжу тоже пишешь с this переменные. Или всегда так писал? А вот Wolsh нервничает от этого, и вроде не только он
Старый 26.04.2014 22:03 toFL вне форума
toFL
Цитата:
dimarik - гляжу тоже пишешь с this переменные. Или всегда так писал? А вот Wolsh нервничает от этого, и вроде не только он
Как по мне, приватные переменные, начинающиеся с буквы m (как в Starling) вполне логично смотрятся.
Старый 27.04.2014 13:16 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Если раз и навсегда привыкнуть к this, легче потом переходить на JavaScript
Старый 29.04.2014 10:50 dimarik вне форума
dimarik
 
Аватар для dimarik
Цитата:
А что с Array? Тоже самое или такой проблемы нет?
Подтверждаю, с Array такой проблемы нет. Можно через указание его длины управлять памятью.
Старый 29.04.2014 11:22 toFL вне форума
toFL
Цитата:
Подтверждаю, с Array такой проблемы нет. Можно через указание его длины управлять памятью.
Спасибо за инфу. Переписываем код с векторов на массивы?
Старый 29.04.2014 22:29 dimarik вне форума
dimarik
 
Аватар для dimarik
Уже переписал.
 

 


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


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