поиск

Использование класса Vector в ActionScript 3 и Flash Player 10

Намусорил: Юрий «Бармалей» Яровой
В категории: Новости

С любезного разрешения Майка Чемберза (Mike Chambers), публикую перевод на русский язык его статьи «Using Vectors in ActionScript 3 and Flash Player 10». Дальнейшее повествование идет от имени Майка.

Одной из новых возможностей, появившихся в Flash Player 10 Public Beta, является включение в эту версию плеера нового класса Vector. По существу, класс Vector является массивом, но в дополнение к функционалу массива он отслеживает тип хранимых элементов данных, и поэтому может обеспечить (иногда довольно существенный) прирост производительности по сравнению с обычным массивом.

Пользоваться классом Vector так же просто, как и пользоваться классом Array. Фактически, класс Vector содержит все те же методы, что и класс Array, и главным отличием между ними является то, как вы создаете экземпляры этих классов.

Для примера, вот так вы инстанцируете экземпляр массива:

Actionscript:
  1. var a:Array = new Array();

ну или вот так:

Actionscript:
  1. var b:Array = [];

А это пример создания экземпляра вектора, который будет хранить объекты с типом int:

Actionscript:
  1. // var ИМЯ_ПЕРЕМЕННОЙ:Vector.<ТИП_ХРАНИМЫХ_ЭЛЕМЕНТОВ> = new Vector<ТИП_ХРАНИМЫХ_ЭЛЕМЕНТОВ>();
  2. var vector:Vector.<int> = new Vector.<int>();

Точно так же, как и в случае использования массива, вы можете инстанцировать экземпляры вектора конкретного размера, передавая длину в качестве первого необязательного параметра конструктора:

Actionscript:
  1. var size:int = 7;
  2. var vector:Vector.<int> = new Vector.<int>(size);

Кроме того, конструктор вектора имеет второй необязательный аргумент в виде булева флага, определяющего должен ли текущий экземпляр Vector быть фиксированного размера (true), либо же его длина в дальнейшем может изменяться (false). По умолчанию этот параметр имеет значение false. В дальнейшем его можно изменить обратившись к свойству fixed экземпляра класса Vector:

Actionscript:
  1. var size:int = 7;
  2. var fixed:Boolean = true
  3. var vector:Vector.<int> = new Vector.<int>(size, fixed);
  4. vector.fixed = !fixed;

Имейте в виду, что если свойство fixed установлено в true, то далее вы уже не можете вызывать методы изменяющие длину массива, например, методы pop(), push(), shift() и т.д.

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

Actionscript:
  1. var s:String = "I am a string";
  2. var d:Date = new Date();
  3. var n:Number = 1138;
  4. var a:Array = new Array();
  5. a[0] = s;
  6. a[1] = d;
  7. a[2] = n;
  8.  
  9. trace(a[1] is Date); // true

Однако в этом случае у вас возникнут ошибки на этапе компиляции:

Actionscript:
  1. var s:String = "I am a string";
  2. var d:Date = new Date();
  3. var n:Number = 1138;
  4. var v:Vector.<String> = new Vector.<String>();
  5. v[0] = s;
  6. v[1] = d;
  7. v[2] = n;
  8.  
  9. trace(v[1] is Date); // false
  10.  
  11. // Ошибки этапа компиляции:
  12. // Implicit coercion of a value of type Date to an unrelated type String.       
  13. // Implicit coercion of a value of type Number to an unrelated type String.

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

Actionscript:
  1. var vector:Vector.<int> = new Vector.<int>();
  2.  
  3. var rand:Number;
  4. for(var i:int = 0; i <1000000; i++)
  5. {
  6.         rand = (Math.floor(Math.random() * 1000000) as int);
  7.         vector.push(rand);
  8. }
  9. trace(vector[7]);

И последнее, что нужно иметь в виду при работе с векторами, заключается в том, что Vector представляет собой вариант «уплотненного» массива. Фактически, это означает, что все элементы, содержащиеся в экземпляре класса Vector должны иметь какое-либо значение или быть равными null. Например, при использовании массива вы можете свободно сделать следующее:

Actionscript:
  1. var a:Array = new Array();
  2. a[0] = "foo";
  3. a[6] = "bar";

Однако, если вы попробуете проделать то же самое с экземпляром Vector, то вы получите ошибку RangeError на этапе исполнения:

Actionscript:
  1. var v:Vector.<String> = new Vector.<String>();
  2. v[0] = "foo";
  3. v[6] = "bar";

Чтобы исправить это, зададим вектору длину при его создании:

Actionscript:
  1. var v:Vector.<String> = new Vector.<String>(7);
  2. v[0] = "foo";
  3. v[6] = "bar";

Ниже приведен пример, который показывает разницу в производительности при работе с вектором и массивом, каждый из которых содержит по миллиону чисел. Имейте в виду, что представленный ниже код — это только один специфичный тест, и повышение производительности в случае использования класса Vector в каждом конкретном приложении может быть как больше, так и меньше.

Actionscript:
  1. package
  2. {
  3.         import flash.display.Sprite;
  4.  
  5.         public class VectorTest extends Sprite
  6.         {
  7.                 private static const NUM_LOOPS:int = 5;
  8.                 public function VectorTest()
  9.                 {       
  10.  
  11.                         var vector:Vector.<int> = new Vector.<int>();
  12.                         var array:Array = new Array();
  13.  
  14.                         // Наполняем данными.
  15.                         var rand:Number;
  16.                         for(var i:int = 0; i <1000000; i++)
  17.                         {
  18.                                 rand = (Math.floor(Math.random() * 1000000) as int);
  19.                                 vector.push(rand);
  20.                                 array.push(rand);
  21.                         }
  22.  
  23.                         var sTime:Number = getMilliseconds();
  24.                         loopArray(array);
  25.                         trace("Loop Array Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
  26.  
  27.                         sTime = getMilliseconds();
  28.                         loopVector(vector);
  29.                         trace("Loop Vector Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
  30.  
  31.                 }
  32.  
  33.                 private function getMilliseconds():Number
  34.                 {
  35.                         return (new Date()).getTime();
  36.                 }
  37.  
  38.                 private function loopArray(a:Array):void
  39.                 {
  40.                         var len:Number = a.length;
  41.  
  42.                         var n:int;
  43.                         for(var i:int = 0; i <NUM_LOOPS; i++)
  44.                         {
  45.                                 for(var k:int = 0; k <len; k++)
  46.                                 {
  47.                                         n = a[k];
  48.                                 }
  49.                         }
  50.                 }
  51.  
  52.                 private function loopVector(v:Vector.<int>):void
  53.                 {
  54.                         var len:Number = v.length;
  55.  
  56.                         var n:int;
  57.                         for(var i:int = 0; i <NUM_LOOPS; i++)
  58.                         {
  59.                                 for(var k:int = 0; k <len; k++)
  60.                                 {
  61.                                         n = v[k];
  62.                                 }
  63.                         }
  64.                 }
  65.         }
  66.  
  67. }

На моей машине вывелись следующие значения:

CODE:
  1. Loop Array Avg (5) : 115.8
  2. Loop Vector Avg (5) : 108.8

Что является довольно значительной разницей, с учетом простоты теста (выборка значения элемента по индексу).

Вы можете найти больше информации о классе Vector, обратившись к документации по Flash Player 10 Beta, а так же к информации о Flash Player 10 на Adobe Labs.

См. также:



Kомментариев - 4 к «Использование класса Vector в ActionScript 3 и Flash Player 10»

Anton Volkov [10 сентября, 2008 в 10:35]

Спасибо за перевод!
Но, пожалуй, не соглашусь с оценкой.

На мой взгляд прирост в 7% ничтожен, и в этом простом тесте это как раз завышенное значение.
Если добавить в цикл какие-то расчёты, ускорение от обращения к Vector станет ещё меньше.

Типизация, а соответственно, и упрощение внутренней организации, и отсутствие лишних преобразований/проверок, мгновенное получение элемента по индексу, должны были дать ускорение в разы!

Вобщем, то же самое что и с "поддержкой 3D".

Юрий Яровой [10 сентября, 2008 в 14:35]

Мне кажется результаты теста будут более впечатляющими, если провести его с использованием объектов более сложного типа, чем int.

Ryan [15 сентября, 2008 в 18:47]

Довльно быстро плеер обновляют. Не знал, что уже 10-я версия на подходе.

Создание экземпляра Vector с заранее определенным содержимым — Garbage Collector [29 октября, 2008 в 14:46]

[...] «Использование класса Vector в ActionScript 3 и Flash Player 10» [...]

Написать комментарий:

Bы можете использовать следующие теги для форматирования: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>



User's collector

Внимание!
Эта опция станет доступной только после того как вы авторизуетесь.


 запомнить меня 
Я новый пользователь

На правах рекламы