Thứ Hai, 25 tháng 3, 2013

Cách tối ưu code trong lập trình mobile

1. vấn đề dùng canvas
Dùng nhiều canvas là ko nên 

chỉ nên dùng 1 Canvas trong project J2ME
lí do : 
- dùng 1 Canvas sẽ tránh được hiện tượng giật hình (khi chuyển canvas này sang canvas nọ)
- không phải get graphics nhiều lần, vì chỉ có mỗi 1 canvas, get graphics 1 lần duy nhất
- bộ thu gom gc cũng ko phải làm việc nhiều

2. vấn đề bộ nhớ & giải phóng bộ nhớ tự động
mặc dù j2me có bộ thu gom bộ nhớ tự động nhưng trong J2ME chờ để bộ thu gom hoạt động thì lúc đó 
ứng dụng đã out of memory từ lâu rồi nhé  .nguyên nhân thì hỏi chúa @_@
tốt nhất là tự tay giải phóng 

cách giải phóng :

bạn gán null tất cả các object được khởi tạo (những object ko còn dùng đến) và gọi lệnh gc như sau

=> khuyến cáo dùng Runtime.getRuntime().gc(); 

lúc nào thì giải phóng

- thường đối với 1 j2me apps thì lúc nào bạn ko cần dùng nữa thì sẽ giải phóng,
- đối với 1 j2me game, thực tế người ta sẽ dùng 1 thread quét định kì (0.5s) , gọi lệnh gc ở trên liên tục

biến nào chiếm nhiều bộ nhớ nhất 
- dĩ nhiên là biến String, chiếm đến >=60% bộ nhớ của ứng dụng j2me thông thường.bạn có thể enable memory monitor lên để kiểm tra điều này => hạn chế dùng biến String, nếu dùng thì nên dùng String buffer. String buffer có thể hiểu nôm na là dùng đến đâu thì chiếm bộ nhớ đến đó.\
- hạn chế dùng biến int, nên dùng short,byte nếu có thể
- hạn chế dùng các biến Image, các image nếu ko transparent thì nên để định dạng jpg, nếu image kích thước 320x240 nên để dung lượng tầm 10kb là vừa
- hạn chế dùng thread, thread là 1 nguyên nhân để bộ nhớ tăng vọt thất thường.khuyến cáo là dùng tối đa 3 thread trong 1 dự án j2me. 3 thread thì máy tàu giật điên cuồng rồi thì phải. nên dùng timer nếu có thể. 
Kinh nghiệm của mình là dùng tối đa 1 thread, thay thế = timer nếu có thể

- nếu dùng thread,timer thì trước khi hủy class chứa nó cần phải hủy nó trước. thực tế là nếu hủy class chứa timer mà ko hủy timer trước thì dù có gọi gc, bộ nhớ vẫn tăng vọt...biết chết liền

trong j2me vấn đề tối ưu bộ nhớ khá hay, làm nhiều sẽ rút ra được kinh nghiệm. chả như android, cứ khai báo biến quên ngày tháng mà ko cần lo nghĩ gì...^^

- jar size : ảnh png 256 colors và dùng lại những vùng ảnh trùng nhau thường là chia ra ảnh thành những mảnh nhỏ và lưu tọa độ lại . Dùng code để sinh lại các chunks của ảnh png.Dùng một thuật toán nén hay hơn libz để nén data vào jar.Code thì nên so sánh các statement và các operator sau khi gen ra JIT code sẽ hơn thua nhau bao nhiêu bytes và ý nghĩa của từng statement trên javac ( không nên tập trung vào đây vì xuống size jar ít lắm nhưng sẽ tốt hơn cho performace ) .
- performace : tối đa việc đẩy người dùng vào cases mà ta có thể tính toán trước trên giấy trong giai đoạn analyzing & design,dynamic struct cho app của bạn ( vẫn ở giai đoạn design),cache data vào mem tối đa có thể ( mâu thuẫn với mem), code chú ý các vòng lặp .Chỉ vẽ lại những vùng cần vẽ trên canvas. 
- mem : Thread và timer sống nhiều sẽ chiếm nhiều mem lý do vì JVM phải tạo ra các stack riêng cho các thread và timer này .Thường thì dùng 1 thread chính rồi kick-off 1 thread done-die liền sau mỗi case.String thường các app thông dụng hay có nhiều => biến nó thành 1 cục data rồi load string từ data lên .Static nhiều sẽ làm hao mem nhưng stable .

 

Chú ý việc khởi tạo các object:

Việc khởi tạo các object rất tốn bộ nhớ, nên chúng ta tránh khởi tạo nó trong vòng lặp for như sau:

 


Code:

        for (int i = 0; i < length; i++) {
ClassName p = new ClassName();
results[i] = p.calculateResult();
}


 

Xem lại vòng lặp của bạn
Nếu bạn dùng vòng lặp kiểu như vậy thì rất dở

Code:

        for (int i = 0; i < v.size(); i++) {
// Làm gì đó
}


Vì mỗi lần lặp, hệ thống sẽ tính toán lại kích thước của v. Thay vào đó hãy tính kích thước của v trước khi vào vòng lặp:

Code:

        int size = v.size();
for (int i = 0; i < size; i++) {
// Làm gì đó
}


Tốt hơn nữa bạn có thể làm như sau:

 

Code:

        for (int i = 0, n = v.size(); i < n; i++) {
// Làm gì đó
}


Còn nếu vòng lặp của bạn không cần quan tâm đến thứ tự của các item lặp, thì hãy chọn cách lặp ngược về 0 vì ngôn ngữ nào cũng vậy, so sánh với số 0 bao giờ cũng hiệu quả hơn hẳn:

 

Code:

        for (int i = v.size() - 1; i >= 0; i--) {
// Làm gì đó
}


 

Sử dụng mảng một chiều thay cho mảng đa chiều

Nếu được thì dùng toán tử shift thay cho các toán tử toán học khác
Chẳng hạn ta có thể dùng int a = 11 << 1 thay cho int a = 11 * 2
Tuy nhiên nếu bạn không rành về toán tử shift thì mình khuyến cáo là không nên dùng.

Tránh sử dụng synchronization nếu không cần thiết
Cuối cùng là sử dụng obfuscater khi biên dịch ứng dụng.

0 nhận xét:

Đăng nhận xét