Armazenamento do bitmap em cache

Use o recurso de armazenamento de bitmap em cache para conteúdo complexo de vetores, quando apropriado.

Uma boa otimização pode ser feita por meio do uso do recurso de armazenamento de bitmaps em cache. Este recurso armazena um objeto de vetor no cache, o renderiza internamente como um bitmap e usa o bitmap para renderização. O resultado pode ser um enorme aumento do desempenho da renderização, mas isso pode requerer uma quantidade significativa de memória. Use o recurso de armazenamento de bitmap em cache para conteúdo de vetores complexos, como gradientes ou textos complexos.

Ligar o caching de bitmap para um objeto animado que contenha gráficos vetoriais complexos (como um texto ou gradientes) melhora o desempenho. Contudo, se o armazenamento em cache de bitmap estiver ativado em um objeto de exibição tal como um clipe de vídeo cuja linha de tempo esteja em execução, você poderá obter o resultado oposto. Em cada quadro, o caching feature precisa atualizar o bitmap armazenado em cache e, em seguida, redesenhá-lo na tela, o que requer muito ciclos de CPU. O recurso de armazenamento de bitmap em cache é uma vantagem apenas quando o bitmap em cache pode ser gerado uma vez e então usado sem ser atualizado.

Se você ativar o armazenamento de bitmap em cache para um objeto Sprite, o objeto pode ser movido sem obrigar o tempo de execução a gerar novamente o bitmap armazenado em cache. Alterar as propriedades x e y do objeto não causa uma nova geração. No entanto, qualquer tentativa de girá-lo, dimensioná-lo ou mudar seu valor alfa faz com que o tempo de execução gere novamente o bitmap armazenado em cache, o que prejudica o desempenho.

Nota: A propriedade DisplayObject.cacheAsBitmapMatrix disponível no AIR e o Packager para iPhone não têm essa limitação. Usando a propriedade cacheAsBitmapMatrix , você pode girar, dimensionar, inclinar e alterar o valor alfa de um objeto de exibição sem acionar uma nova geração do bitmap.

Um bitmap em cache pode usar mais memória do que uma instância comum de clipe de filme. Por exemplo, se o clipe de filme no Palco tiver 250 x 250 pixels, quando armazenado em cache ele usará cerca e 250 KB, em vez de 1 KB, usado quando não armazenado em cache.

O exemplo a seguir envolve um objeto Sprite que contém a imagem de uma maçã. A classe a seguir é anexada ao símbolo da maçã:

package org.bytearray.bitmap 
{     
    import flash.display.Sprite; 
    import flash.events.Event; 
     
    public class Apple extends Sprite 
    { 
        private var destinationX:Number; 
        private var destinationY:Number; 
         
        public function Apple () 
        { 
            addEventListener(Event.ADDED_TO_STAGE,activation); 
            addEventListener(Event.REMOVED_FROM_STAGE,deactivation);     
        } 
         
        private function activation(e:Event):void  
        { 
            initPos();     
            addEventListener (Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function deactivation(e:Event):void  
        { 
            removeEventListener(Event.ENTER_FRAME,handleMovement);     
        } 
         
        private function initPos():void 
        { 
            destinationX = Math.random()*(stage.stageWidth - (width>>1)); 
            destinationY = Math.random()*(stage.stageHeight - (height>>1)); 
        } 
         
        private function handleMovement(e:Event):void  
        { 
            x -= (x - destinationX)*.5; 
            y -= (y - destinationY)*.5; 
             
            if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
                initPos(); 
        } 
    } 
}

O código usa a classe Sprite em vez da classe MovieClip, porque uma linha de tempo não é necessária para cada maçã. Para aumentar ao máximo o desempenho, use o objeto mais leve possível. Em seguida, a classe é instanciada com o seguinte código:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(MouseEvent.CLICK,createApples); 
stage.addEventListener(KeyboardEvent.KEY_DOWN,cacheApples); 
 
const MAX_NUM:int = 100; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
function createApples(e:MouseEvent):void 
{ 
    for (var i:int = 0; i< MAX_NUM; i++) 
    { 
        apple = new Apple(); 
         
        holder.addChild(apple); 
    } 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holder.numChildren; 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holder.getChildAt (i) as Apple; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

Quando o usuário clica no mouse, as maçãs são criadas sem armazenamento em cache. Quando o usuário pressiona a tecla C (código de tecla 67), os vetores da maçã são armazenados em cache como bitmaps e mostrados na tela. Essa técnica aumenta muito o desempenho da renderização, tanto em computadores desktop quanto em dispositivos móveis, quando a CPU é lenta.

No entanto, embora o uso do recurso de armazenamento de bitmap em cache aumente o desempenho da renderização, ele pode consumir rapidamente grandes quantidades de memória. Assim que um objeto é armazenado em cache, sua superfície é capturada como um bitmap transparente e armazenada na memória, conforme mostrado no seguinte diagrama:

Bitmap do objeto e de sua superfície armazenado na memória

O Flash Player 10.1 e o AIR 2.5 otimizam o uso de memória usando a mesma abordagem descrita em Filtros e descarregamento dinâmico de bitmap . Se um objeto de exibição armazenado em cache estiver oculto ou fora da dela, seu bitmap na memória é liberado quando ficar sem uso por um tempo.

Nota: Se a propriedade opaqueBackground do objeto de exibição for definida com uma cor específica, o tempo de execução considerará o objeto como sendo opaco. Quando usado com a propriedade cacheAsBitmap , o tempo de execução cria um bitmap não transparente de 32 bits na memória. O canal alfa é definido como 0xFF, o que aumenta o desempenho, porque nenhuma transparência é necessária para desenhar o bitmap na tela. Evitar a mescla alfa torna a renderização ainda mais rápida. Se a profundidade atual da tela estiver limitada a 16 bits, o bitmap na memória será armazenado como uma imagem de 16 bits. Utilizar a propriedade opaqueBackground não ativa o armazenamento de bitmap implicitamente.

Para economizar memória, use a propriedade cacheAsBitmap e ative-a em cada objeto de exibição em vez de fazê-lo no container. Ativar o armazenamento de bitmap em cache no container torna o bitmap final muito maior na memória, criando um bitmap transparente com dimensões de 211 x 279 pixels. A imagem usa cerca de 229 KB de memória:

Exibir gráfico inteiro
Ativação do armazenamento de bitmap em cache no container

Além disso, ao armazenar o contêiner, você corre o risco atualizar todo o bitmap na memória, caso qualquer maçã comece a se mover em um quadro. A ativação do armazenamento de bitmap em cache em cada instância individual resulta no armazenamento em cache de seis superfícies de 7 KB na memória, o que usa somente 42 KB de memória:

Exibir gráfico inteiro
Ativação do armazenamento de bitmap em cache nas instâncias

Acessar cada instância da maçã por meio da lista de exibição e chamar o método getChildAt() armazena referências em um objeto Vector para tornar o acesso mais fácil:

import org.bytearray.bitmap.Apple; 
 
stage.addEventListener(KeyboardEvent.KEY_DOWN, cacheApples); 
 
const MAX_NUM:int = 200; 
var apple:Apple; 
var holder:Sprite = new Sprite(); 
 
addChild(holder); 
 
var holderVector:Vector.<Apple> = new Vector.<Apple>(MAX_NUM, true); 
 
for (var i:int = 0; i< MAX_NUM; i++) 
{ 
    apple = new Apple(); 
     
    holder.addChild(apple); 
     
    holderVector[i] = apple; 
} 
 
function cacheApples(e:KeyboardEvent):void 
{ 
    if (e.keyCode == 67) 
    { 
        var lng:int = holderVector.length 
         
        for (var i:int = 0; i < lng; i++) 
        { 
            apple = holderVector[i]; 
             
            apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap); 
        } 
    } 
}

Tenha em mente que o armazenamento de bitmap aumenta a renderização caso o conteúdo armazenado não seja rotacionado, dimensionado ou alterado a cada quadro. Entretanto, para qualquer transformação que não seja translação nos eixos x e y, a renderização não é aprimorada. Nesses casos, o Flash Player atualiza a cópia do bitmap no cache para cada transformação que ocorra no objeto exibido. Atualizar a cópia em cache pode resultar em um alto uso da CPU, em baixo desempenho e em alto consumo de bateria. Da mesma forma, a propriedade cacheAsBitmapMatrix disponível no AIR ou no Packager para iPhone não tem essa limitação.

O código a seguir altera o valor alfa no método de movimento, que altera a opacidade da maçã em cada quadro:

private function handleMovement(e:Event):void  
{ 
        alpha = Math.random(); 
        x -= (x - destinationX)*.5; 
        y -= (y - destinationY)*.5; 
             
        if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1) 
            initPos(); 
}

O uso do armazenamento de bitmap em cache causa lentidão do desempenho. Alterar o valor alfa força o tempo de execução a atualizar o bitmap em cache na memória sempre que o valor alfa for modificado.

Filtros dependem de bitmaps que são atualizados sempre que a cabeça de reprodução de um clipe de filme armazenado em cache se move. Assim, usar um filtro define automaticamente a propriedade cacheAsBitmap como true . A figura a seguir ilustra um clipe de filme animado:

Clipe de filme animado

Evite usar filtros em conteúdo animado, visto que isso pode causar problemas de desempenho. Na figura a seguir, o designer adiciona um filtro de sombra:

Clipe de filme animado com filtro de sombra projetada

Como resultado, se a linha de tempo dentro do clipe de filme está sendo reproduzida, o bitmap precisa ser gerado novamente. O bitmap também precisa ser gerado novamente se o conteúdo for modificado de qualquer forma diferente de uma simples transformação x ou y. Cada quadro força o tempo de execução a redesenhar o bitmap, o que requer mais recursos da CPU, reduz o desempenho e consome mais vida útil da bateria.

Paul Trani fornece exemplos de utilização do Flash Professional e do ActionScript para otimizar gráficos usando bitmaps no seguinte vídeo de tutorial: