Показать сообщение отдельно
Старый 07.05.2016, 02:10
Bletraut вне форума Посмотреть профиль Отправить личное сообщение для Bletraut Найти все сообщения от Bletraut
  № 1  
Ответить с цитированием
Bletraut
 
Аватар для Bletraut

Регистрация: Mar 2013
Адрес: Вне пространства.
Сообщений: 567
Отправить сообщение для Bletraut с помощью ICQ Отправить сообщение для Bletraut с помощью Skype™
Attention БАГ или УТЕЧКА памяти в слиянии массивов!?

Обнаружил кое-что странное, не знаю точно является ли это багом или утечкой памяти, а может быть это вообще нормальная работа флеш плеера...
Суть в следующем: есть у меня в игре парсер 3д моделей, так вот, для слияния двух массивов с данными я использовал функцию concat и всё бы ничего, пока я не решил загрузить очень тяжелую модель. И заметил, что парсинг идет не плавно, как это должно быть, а постепенно замедляется. Исследовав код парсера обнаружил, что всё дело в функции concat, которая объединяет данные из нескольких массивов в один.

Для теста сделал следующее:

Код AS3:
 
var t:int = getTimer();
 
var a:Array = new Array();
var b:Array = [1, 2, 3, 4, 5];
for (var i:int = 0; i < 250000; i++)
{
	a = a.concat(b); // Вываливается с ошибкой, что скрипт слишком долго выполняется
}
trace(getTimer() - t + "ms");
 
for (i = 0; i < 250000; i++)
{
	for (var k:int = 0; k < b.length; k++) a.push(b[k]); // Здесь всё нормально, 250 ms
}
trace(getTimer() - t + "ms");
 
for (i = 0; i < 250000; i++)
{
	for (var k:int = 0; k < b.length; k++) a[a.length] = b[k]; // Здесь всё нормально, 227 ms
}
trace(getTimer() - t + "ms");
Не знаю точно, что именно происходит в методе concat, но есть предположение, что при каждом вызове метода, создается новый экземпляр массива и сборщик мусора не успевает очищать память, тем самым появляются лаги. Прав я или нет? Стоит ли писать адобу в поддержку или же это нормальное явление?

Сейчас решил проверить свою гипотезу, сделал функцию аналогичную concat:
Код AS3:
var t:int = getTimer();
 
var a:Array = new Array();
var b:Array = [1, 2, 3, 4, 5];
for (var i:int = 0; i < 250000; i++)
{
	a = myConcat(a, b); // Вывалилось с ошибкой.
}
trace(getTimer() - t + "ms");
 
private function myConcat(m:Array, ...rest):Array
{
	var a:Array = new Array();
	for (var i:int = 0; i < m.length; i++) a.push(m[i]);
 
	for (i = 0; i < rest.length; i++)
	{
		for (var j:int = 0; j < rest[i].length; j++) a.push(rest[i][j]);
	}
 
	return a;
}
Получается, что concat это самый настоящий баг???

Всё нормально.
__________________
Я заклинаю вас действовать иначе.


Последний раз редактировалось Bletraut; 07.05.2016 в 14:11.