Home > Flash/Flex/AIR, Optimization > Optimizing Mobile Content for the Adobe Flash Platform – Conserving memory

Optimizing Mobile Content for the Adobe Flash Platform – Conserving memory

Display objects:

-Chúng ta nên sử dụng Shapes cho những display object không tương tác với user, mà chỉ có duy nhất chức năng hiển thị.

-Sử dụng Sprite cho những display object có tương tác nhưng không có timeline animation.

-MovieClip sẽ là lựa chọn cuối cùng khi chúng ta thật sự cần nó.

Bạn có thể xem ví dụ code sau:

trace(getSize(new Shape()));
// output: 236
trace(getSize(new Sprite()));
// output: 412
trace(getSize(new MovieClip()));
// output: 440

Trong đó hàm getSize() sẽ trả về số bytes của display object được tạo ra lưu trong memory. Ta thấy MovieClip và Sprite có thể tăng gấp đôi vùng nhớ trong memory so với Shape.

Primitive types

– Ví dụ sao đây cho bạn thấy số bytes của từng kiểu Number, int, uint, Boolean, String sẽ tạo ra trong vùng nhớ:

// Primitive types
var a:Number;
trace(getSize(a));
// output: 8 

var b:int;
trace(getSize(b));
// output: 4 

var c:uint;
trace(getSize(c));
// output: 4 

var d:Boolean;
trace(getSize(d));
// output: 4 

var e:String;
trace(getSize(e));
// output: 4

– Kiểu Number sẽ được cấp phát tùy theo giá trị được khởi tạo là 4 hoặc 8 bytes (Nếu chúng ta không gán giá trị ban đầu khi khởi tạo thì nó sẽ được cấp phát 8 bytes)

// Primitive types
var a:Number = 8;
trace(getSize(a));
// output: 4

var a:Number;
trace(getSize(a));
// output: 8

var a:Number = Number.MAX_VALUE;
race(getSize(a));
// output: 8

-Tương tự kiểu String cũng được cấp phát theo giá trị khởi tạo (Nếu không khởi tạo thì nó được cấp phát 4 bytes)

var name:String;
trace(getSize(name));
// output: 4 

name = "";
trace(getSize(name));
// output: 24 

name = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularized in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
trace(getSize(name));
// output: 1172

Ta nên hạn chế khởi tạo String = “” nếu không cần thiết, điều này sẽ lãng phí một ít vùng nhớ khi String này không được sử dụng, đặc biệt khi ta khởi tạo các thuộc tính String của một class:

class Person {
     public var att1: String = "";
     public var att2: String = "";
     public var att3: String = "";
     public var att4: String = "";
}

Khi var p: Person = new Person() thì p sẽ chiếm 24 x 4 = 96 bytes vùng nhớ, trong khi không khởi tạo thì chỉ mất 4 x 4 = 16 bytes

Reusing objects

Sử dụng lại đối tượng đã khai báo cũng là một cách tiết kiệm vùng nhớ.

const MAX_NUM:int = 18;
const COLOR:uint = 0xCCCCCC; 

// Create the rectangle outside the loop
var area:Rectangle = new Rectangle(0,0,1,10); 

for (var:int = 0; i < MAX_NUM; i++)
{
    //Don't use: area = new Rectangle(0,0,1,10); in loop
    area.x = i;
    myBitmapData.fillRect(area,COLOR);
}

Một ví dụ khác:

// Create a single 20 x 20 pixel bitmap, non-transparent
var myImage:BitmapData = new BitmapData(20,20,false,0xF0D062);
var myContainer:Bitmap;
const MAX_NUM:int = 300;
for (var i:int = 0; i< MAX_NUM; i++)
{
    // Create a container referencing the BitmapData instance
    myContainer = new Bitmap(myImage);
    // Add it to the display list
    addChild(myContainer);
    // Place each container
    myContainer.x = myContainer.width * Math.round(i % 20);
    myContainer.y = myContainer.height * int(i / 20);
}

Đoạn code này đã tiết kiệm được 700Kb bộ nhớ (rất có ý nghĩa với một bộ nhớ trên mobile) so với chúng ta “new Bitmapdata” trong loop.

Freeing memory

-Như chúng ta đã biết Garbage Collection của Flash Player chỉ xóa vùng nhớ khi không còn đối tượng nào refference đến vùng nhớ đó. Lưu ý trên Flash Player, Garbage Collection tự động chạy chứ không được kích hoạt bằng code (có khi nó cũng chẳng thèm chạy nếu bộ nhớ còn nhiều,😦 hic hic thành ra memory có thể cache lại các đối tượng như connection, image, sound, audio . . .  dù ta đã xóa hết reference).

-Điều này cũng khó trách bởi việc khởi động và vận hành Garbage Collection sẽ ngốn tài nguyên và xử lý CPU để thực hiện truy vết theo dạng cây phức tạp các reference đến vùng nhớ, từ đó xác định xem vùng nhớ có thật sự không còn ai sử dụng nữa không. Nếu một ứng dụng flash ngốn quá nhiều memory nó sẽ khởi động Garbage Collection thường xuyên hơn, dẫn đến chiếm dụng thêm CPU, chậm càng chậm hơn. Chính vì vậy mặc dù  có thể khởi động Garbage Collection trong AIR và flash debugger bằng System.gc() nhưng Adobe khuyến cáo rằng đừng nên lạm dụng và thiếu kiểm soát.

-Do đó để freeing memory chúng ta phải đảm bảo rằng các reference đã được xóa bằng cách gắn null. Với as1 và as2 thì dùng hàm delete, lưu ý hàm delete trong as3 có tính năng khác hoàn toàn, nó dùng để delete một dynamic properties trong một dynamic object ví dụ:

var t:* = new Timer(15);
trace(delete(t.delay));
// traces false
// vì ta không thể delete properties của object không dynamic
trace(t.delay); // 15 - delete never occurred 

var o:* = {fun:"stuff"};
trace(delete(o.fun));
// traces true
// Object là kiểu dynamic nên ta có thể delete dynamic properties của nó là fun
trace(o.fun); // undefined - delete occurred
trace(delete(o.foo)); // true, because foo is not defined after delete

-Một lưu ý khác: khi một đối tượng dùng hàm addEventListner:

var obj: MovieClip = new MovieClip();
obj.addEventListener(MouseEvent.CLICK, clickObjHandler);
. . .
//thì việc obj = null vẫn chưa xóa được vùng nhớ. Ta phải:
obj.removeEventListener(MouseEvent.CLICK, clickObjHandler);
//rồi sau đó mới:
obj = null;
//Vì trong hàm addEventListner đã tạo ra tham chiếu đến vùng nhớ.

-Không giống như các đối tượng khác BitmapData có thể được dọn dẹp ra khỏi vùng nhớ ngay lập tức khi ta dùng hàm dispose()

trace(System.totalMemory / 1024);
// output: 43100 

// Create a BitmapData instance
var image:BitmapData = new BitmapData(800, 600); 

trace(System.totalMemory / 1024);
// output: 44964 

image.dispose();
image = null; 

trace(System.totalMemory / 1024);
// output: 43084 

-Flex SDK 3.5 có giới thiệu một hàm static mới System.disposeXML(node: XML) để xóa các reference đến node XML và sẵn sàng cho đợt dọn rác tiếp theo của Garbage Collection.

Using bitmaps

Sử dụng ảnh Bitmap hay Vector là đề tài tranh cãi trên diễn đàn hay blog flash. Bởi vì Bitmap sẽ ngốn nhiều tài nguyên memory (cụ thể là RAM) hơn là Vector nhưng Vector lại chiếm dụng CPU hoặc GPU cho việc render (Flash Player cần ít xử lý để vẽ từng pixel ảnh, hơn là render một ảnh vector, đặc biệt với số lượng lớn ảnh vector có thể khiến CPU hoặc GPU quá tải). Theo quan điểm của mình thì chúng ta sử dụng Bitmap sẽ tốt hơn (trong trường hợp có nhiều đồ họa, dĩ nhiên là chúng ta không nên quá lạm dụng mà phải optimize giữa chất lượng và kích thướt  bitmap tương đối), và đây cũng là điều Adobe khuyên chúng ta vì:

-Ngày nay với các máy PC hoặc MAC thì việc nâng cấp RAM dễ dàng và rẻ tiền hơn nâng cấp CPU hoặc GPU. Thường các máy luôn có RAM lớn hơn 1G (dư hơi cho các ứng dụng nhiều đồ họa).

-Với các thiết bị chạy Android thì bộ nhớ luôn lớn hơn 512MB, nhưng tốc độ CPU lại thấp <= 1GHz, ít thiết bị có GPU riêng lẻ.

-Flash Player 10.1 sắp tới, support tính năng mới Bitmap downsampling sẽ tự động giảm ảnh bitmap từ 32 bit xuống 16 bit, để tiết kiệm bộ nhớ, nếu nó detect thấy màn hình thiết bị đang chạy ở chế độ màu 16 bit, tính năng này chủ yếu support trên Window Mobile. Ví dụ một hình bitmap kich thướt 300 x 300 sẽ chiếm bộ nhớ: 300*300*4/1024 = 350 KB ở chế độ màu 32 bit, nhưng ở chế độ màu 16 bit nó chỉ chiếm 175 KB trong bộ nhớ.

-Thêm một tính năng đặc sắc nữa, Flash Player 10.1 giới thiệu BitmapData single reference chạy trên mọi platform. Khi một instance BitmapData được tạo ra từ ảnh nhúng, thì một bản sao BitmapData của nó sẽ được sử dụng cho mọi instance Bitmapdata khác muốn dùng đến ảnh nhúng đó. Như vậy Flash Player 10.1 chỉ lưu một BitmapData trong vùng nhớ và sử dụng cho nhiều instance để hiển thị cùng một hình ảnh. Chỉ khi ta muốn edit nội dung hình ảnh đó trên một instance thì Flash Player mới cấp phát một vùng nhớ mới cho instance đó.

Tính năng này tiết kiệm rất nhiều vùng nhớ qua ví dụ đơn giản sau:

const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
    for (var j:int = 0; j<MAX_NUM; j++)
    {
        star = new Star(0,0);
        bitmap = new Bitmap(star);
        bitmap.x = j * star.width;
        bitmap.y = i * star.height;
        addChild(bitmap)
    }
}


Nếu với các bản Flash Player trước đây, đoạn code này sẽ tiêu tốn 1296 KB hơn 1 MB, nhưng với Flash Player 10.1 chỉ tốn 4 KB trong bộ nhớ để lưu duy nhất 1 ảnh ngôi sao trên.

var ref:Bitmap = getChildAt(0) as Bitmap;
ref.bitmapData.pixelDissolve(ref.bitmapData, ref.bitmapData.rect,
    new Point(0,0),Math.random()*200,Math.random()*200, 0x990000);

Đoạn code này lấy bitmap đầu tiên trong display object mà ta đã add ở trên, sau đó chỉnh sửa lại bằng hàm pixelDissolve. Việc này làm phát sinh thêm 1 vùng nhớ mới 4KB để lưu một bitmap khác biệt so với các bitmap còn lại. Như vậy kết hợp đoạn code trên và đoạn code này sẽ chiếm 8 KB trong Flash Player 10.1

(Còn tiếp . . .)

Namheo

  1. dothanhlam
    28/04/2010 at 6:37 am

    Không nói đến animation hả Heo ?

  2. nam12h
    28/04/2010 at 8:45 am

    dạ bài dài quá sợ ko ai đọc, nên em research viết tiếp ở bài sao :-s

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: