terça-feira, 14 de junho de 2011

Usando Array e Vector

Olá pessoal, a muito tempo venho observando com mais atenção os tipos de variáveis que uso em minhas aplicações e, ao longo do tempo fui percebendo que alguns tipos usados, junto com algumas boas práticas, melhoraram de forma considerável a velocidade de minhas aplicações.

Como todo programador iniciante, quando descobrimos o potencial do Array ficamos eufóricos!

“Nossa, agora posso guardar todos meus MovieClips num Array!”

“Posso guardar várias frases de alerta num mesmo lugar!”

E por ai vai… E quase sempre guardamos o mesmo tipo de valor em todas as posições do Array, então porque não usar um Array tipado? É nesse momento que entra em cena o Vector. Além de umas funcionalidades a mais, o Vector tem o mesmo comportamento que um Array, exceto que os valores em cada posição agora são tipados. Por exemplo:

   1: // Um Array que aceita qualquer tipo nas posições.
   2: var meuArray:Array = [];
   3:  
   4: // Um Vector que só aceita MovieClips nas posições.
   5: var meuVector:Vector.<MovieClip> = new Vector.<MovieClip>();

Tá, legal… Mas e qual a vantagem disso?


A principal é em relação ao cast, se você usa Array e quer acessar um MovieClip e, por exemplo, dar um .play() nele, você teria que fazer um cast antes. No caso do Vector não, você já invoca o .play() direto:



   1: //O cast degrada performance em runtime.
   2: MovieClip(meuArray[5]).play();
   3:  
   4: //Sem o cast a aplicação não tem que converter o valor em um tipo.
   5: meuVector[5].play();

Mais uma vantagem é o tamanho pré-definido do Vector, no caso do Array, ao criá-lo você não consegue dizer quantas posições terá. No Vector, ao criá-lo, além de passar o tipo de valor que cada posição terá, você pode dizer qual o tamanho inicial:



   1: // Um Vector de MovieClip com 10 posições.
   2: var meuVector:Vector.<MovieClip> = new Vector.<MovieClip>(10);

Uma observação muito importante sobre isso, ao pré-definir o tamanho, quando o Vector é criado todas as posição recebem o valor padrão do tipo, no caso do MovieClipe é NULL. Por exemplo:



   1: // Um Vector de MovieClip com 10 posições.
   2: var meuVector:Vector.<MovieClip> = new Vector.<MovieClip>(10);
   3: trace( meuVector.length ); // 10
   4: trace( meuVector[3] ); // null

Veja que o Vector já tem 10 posições, mas elas estão nulas (como exemplo a 4° posição). Então atenção, o Vector mesmo com o tamanho pré-definido na criação não trava o PUSH. Então se você der PUSH, o valor será colocado na 11ª posição:



   1: // Um Vector de MovieClip com 10 posições.
   2: var meuVector:Vector.<MovieClip> = new Vector.<MovieClip>(10);
   3:  
   4: trace( meuVector.length ); // 10
   5:  
   6: // Inserindo um novo MovieClipe na 11ª posição.
   7: meuVector.push( new MovieClip() );
   8:  
   9: trace( meuVector.length ); // 11


Falando um pouco sobre o PUSH, além de esse método ser extramente custoso para a aplicação, no caso do Vector do exemplo, ele não tem o comportamento esperado num primeiro momento.


E para fechar de vez o caixão do Array (provavelmente essa colocação vai me custar caro), vou fazer um teste de stress com as três variantes: Array, Vector e Vector com tamanho inicial definido.



   1: import flash.utils.getTimer;
   2:  
   3: const TAM:uint = 1000000; // 1.000.000 (hum milhão)
   4:  
   5: var i:uint;
   6: var time:uint;
   7: var meuArray:Array = [];
   8: var meuVector:Vector.<uint> = new Vector.<uint>();
   9: var meuVectorDef:Vector.<uint> = new Vector.<uint>(TAM);
  10:  
  11: // ARRAY /////////////////////////////////////////////////
  12:  
  13: time = getTimer();
  14:  
  15: for(i = 0; i < TAM; i++)
  16:     meuArray[i] = i;
  17:     
  18: trace('Tempo do Array:', getTimer() - time, 'ms');
  19:  
  20: // VECTOR ///////////////////////////////////////////////
  21:  
  22: time = getTimer();
  23:  
  24: for(i = 0; i < TAM; i++)
  25:     meuVector[i] = i;
  26:     
  27: trace('Tempo do Vector:', getTimer() - time, 'ms');
  28:  
  29: // VECTOR DEFINIDO //////////////////////////////////////
  30:  
  31: time = getTimer();
  32:  
  33: for(i = 0; i < TAM; i++)
  34:     meuVectorDef[i] = i;
  35:     
  36: trace('Tempo do Vector Definido:', getTimer() - time, 'ms');

No meu teste aqui deu o seguinte resultado:


Tempo do Array: 77 ms
Tempo do Vector: 39 ms
Tempo do Vector Definido: 19 ms


Veja que é praticamente a metade do tempo de um pra outro. E faça você um teste com o PUSH para ver o quanto esses valores aumentam…

Nenhum comentário:

Postar um comentário