Chương 5 : Một số cải tiến nhằm tối ưu hóa chương trình
103
// Imports
import javax.microedition.lcdui.Graphics;
public final class g {
// Fields
private static int[] a;
private static short[] b;
private static String[] c;
private static byte[] d;
private static short[] e;
private static short[] f;
private static short[] g;
private static short[] h;
private static short[] i;
private static short[] j;
// Constructors
public g() { }
// Methods
5.3. Tối ưu hóa về tốc độ :
5.3.1. Khái quát chung :
- Khi muốn tối ưu về tốc độ, trước tiên, cần tập trung vào tối ưu việc thiết kế
và lựa chọn giải thuật cho hợp lý, sau đó mới thực hiện việc cải thiện tốc độ ở mức
cấp thấp trên từng dòng lệnh bởi vì phần lớn thời gian chương trình hoạt động được
dùng cho việc thực hiện các hàm xử lý trong thư viện do chúng ta g
ọi đến, đặc biệt
là đối với các chức năng xử lý đồ họa cấp thấp.
- Quy tắc 90/10 : “trong các chương trình có nhu cầu xử lý đồ họa lớn, đặc
biệt là các phần mềm trò chơi hành động, 90% tổng thời gian xử lý của chương
trình dùng để xử lý 10% mã nguồn”. Như vậy, 90% mã nguồn còn lại chỉ cần 10%
thời gian để xử lý. Do đó, chúng ta cần phải tập trung xác định nh
ững thao tác xử lý
nào tiêu tốn nhiều thời gian xử lý nhất để tìm cách tối ưu hóa chúng.
- Hiệu suất thi hành các lệnh không giống nhau trên thiết bị của các nhà sản
xuất khác nhau do mỗi hãng sản xuất có công nghệ và cách cài đặt xử lý theo đặc tả
MIDP khác nhau.
5.3.2. Tìm các vị trí cần tối ưu về tốc độ :
Sử dụng Profiler
Trong bộ công cụ lập trình J2ME của Sun (Sun Wireless Toolkit) có cung
cấp cho chúng ta một tiện ích dùng để thống kê tần suất hoạt động và tài nguyên
CPU dành cho từng chức năng xử lý (công cụ này được gọi là profiler). Dựa vào
Chương 5 : Một số cải tiến nhằm tối ưu hóa chương trình
106
thể xây dựng riêng một đoạn mã nhằm xác định khoảng thời gian dùng cho hàm
bằng cách sử dụng giờ hệ thống :
long startTime = System.currentTimeMillis(); //Trước khi gọi hàm
gọi_hàm();
long timeTaken = System.currentTimeMillis() – startTime; //Khoảng thời gian
thực thi
5.3.3. Các nguyên tắc tăng tốc cho chương trình :
- Chỉ nên tập trung tối ưu các thao tác có số lượng chu kỳ xử lý lớn.
- Hầu hết các hàm trong thư viện đồ họa cấp thấp ví dụ như các hàm vẽ đối
tượng đồ họa cơ sở (đường thẳng, hình chữ nhật, cung, ellipse…), các hàm tô màu
đều sử dụng rất nhiều chu kỳ máy, vì vậy, cần hạn chế số lần gọi các hàm này.
- Sử dụng hàm setClip(…) để hạn chế vùng cần vẽ.
- Đem các tính toán ra bên ngoài vòng lặp nếu có thể.
- Nếu không làm ảnh hưởng đến thiết kế chương trình, cài đặt các phương
thức dạng static final sẽ giúp phương thức được thực hiện nhanh hơn. Tránh sử
dụng phương thức synchronized, phương thức này chậm do phải lock những đối
tượng cần thiết.
Dạng phương thức Tốc độ
synchronized chậm nhất
interface chậm
instance
final nhanh
}
Nhưng, sẽ nhanh hơn nếu chúng ta cài đặt ngược lại :
for (int i=n; i>=0; )
{
…….
}
- Các phép toán trên bit có tốc độ rất cao, vì vậy, nên sử dụng các phép toán
dịch bit (shift left, shift right) thay cho phép toán nhân, chia với các số là lũy thừa
của 2.
- Trong ngôn ngữ Java, việc truy xuất một phần tử của mảng chậm hơn rất
nhiều so với ngôn ngữ C. Mỗi khi chúng ta truy xuất một phần tử, Java đều kiểm tra
chỉ số đưa vào có hợp lệ hay không. Nếu chỉ số này nhỏ hơn 0 hoặc lớn hơn ch
ỉ số
của phần tử cuối thì Java sẽ thông báo ngoại lệ ArrayIndexOutOfBoundsException. Chương 5 : Một số cải tiến nhằm tối ưu hóa chương trình
108
Như vậy, một phần tử trong mảng nếu được truy xuất nhiều lần thì chúng ta nên gán
giá trị của phần tử đó vào một biến trung gian để sử dụng cho những lần tiếp theo.
- Khi cần sao chép mảng, nên sử dụng hàm sao chép do J2ME cung cấp sẵn sẽ
nhanh hơn rất nhiều so với việc sử dụng vòng lặp. Cú pháp như sau :
public class Foo
{
private int[] array;
public void foo()
{
int[] myArray = array;
for (int i = myArray .length; i ; )
{
myArray [i] = i*2;
}
}
}
- Việc khởi tạo một đối tượng cũng mất nhiều thời gian. Do vậy, nếu có thể
được, chúng ta nên tận dụng một đối tượng sẵn có rồi cập nhật lại các giá trị, các
thuộc tính của chúng thay vì tạo một đối tượng mới.
- Phép toán chia thực hiện chậm hơn so với phép toán nhân, vì thế, nếu cần
phải chia nhiều lần cho cùng một số, chúng ta có thể tính nghịch đảo c
ủa số chia rồi
dùng kết quả tìm được nhân với số bị chia.
- Những đoạn chương trình có khai báo try/catch để xử lý các Exception
cũng có tốc độ rất chậm. Do đó, nếu không bị bắt buộc phải khai báo như vậy,
chúng ta không nên sử dụng chúng trong chương trình.
Chương 5 : Một số cải tiến nhằm tối ưu hóa chương trình
111Hình 5-4 : Màn hình giao diện công cụ theo dõi việc sử dụng bộ nhớ
5.4.2. Các nguyên tắc tối ưu hóa việc sử dụng bộ nhớ :
- Sử dụng càng ít đối tượng càng tốt và chỉ cấp phát bộ nhớ khi cần thiết.
- Đối với các đối tượng không còn cần được sử dụng nữa, nên gán cho chúng
giá trị null để giúp garbage collector nhận diện được vùng nhớ không còn được sử
dụng nữa để thu hồi.
- Bộ nhớ của các thiết bị di động rất hạn chế, do vậy, trong thiết kế chương
trình, chúng ta nên tránh việc xây dựng các hàm có nhu cầu được cấp phát khối
lượng bộ nhớ lớn.
- Trong J2ME, việc thu hồi bộ nhớ không còn được sử dụng được thực hiện
thông qua garbage collector. Tuy nhiên, khi nào việc thu dọn này được thực hiện là
do người lập trình tự quyết định. Mặt khác, việc thực thi hàm thu hồi bộ nhớ
System.gc() cũng mất nhiều thời gian. Vì vậy, chúng ta cần quản lý bộ nhớ chặ
t chẽ,
String và StringBuffer. Kết quả là khiến cho chương trình sử dụng và tạo nhiều rác
trong bộ nhớ, mặt khác sẽ làm tăng thời gian xử lý của chương trình do phải mất
nhiều thời gian khởi tạo các đối tượng. Cải tiến đoạn chương trình trên như sau :
Chương 5 : Một số cải tiến nhằm tối ưu hóa chương trình
113
public String indent (String line, int spaces)
{
StringBuffer out = new StringBuffer();
for (int i=0;i<spaces;i++)
{
out.append(‘ ’);
}
return out.toString();
}
Chương 6 : Thử nghiệm – Hướng dẫn cài đặt và sử dụng
115Hình 6-2 : Màn hình giao diện trình giả lập Sony Ericsson
6.1.2. Trình giả lập Nokia :
Bộ công cụ phát triển ứng dụng cho Nokia mới nhất hiện nay có tên là Nokia
Developer’s Suite for Java™ 2 Platform, Micro Edition, Version 2.2 for Windows.
Tập tin cài đặt có kích thước 49 MB, việc cài đặt cũng tương tự như các chương
trình bình thường.
Sau khi cài đặt, thực thi bằng cách chọn trên Start Menu, mục Nokia
Developer’ Suite for J2ME Æ Run as a Standalone. Hộp thoại sau xuất hiện : Chương 6 : Thử nghiệm – Hướng dẫn cài đặt và sử dụng
116
Chương 6 : Thử nghiệm – Hướng dẫn cài đặt và sử dụng
118
Cách 1 :
Bước 1 :
Các ứng dụng cũng như các tập tin tài nguyên (skin, theme, hình ảnh, âm
thanh) được chứa trong thư mục “filesystem\0\” của mỗi trình giả lập. Chúng ta tạo
trong thư mục này một thư mục con chứa 2 tập tin HoChiMinhCity_Map.jad,
HoChiMinhCity_Map.jar (tên thư mục không yêu cầu trùng với tên ứng dụng). Ví
dụ :
c:\Siemens\SMTK_3.X\emulators\SK65\Filesystem\0\HCMCMM\HoChiMinh
City_Map.jad
c:\Siemens\SMTK_3.X\emulators\SK65\Filesystem\0\HCMCMM\HoChiMinh
City_Map.jar
Bước 2 :
Gọi trình giả lập từ bằng cách chọn Start Menu Æ Siemens Mobility Toolkit
3.00 Æ
SMTK 3.0 Emulator Launcher
Chọn trình giả lập Siemens SK65
Bước 3 :
Chọn mục Extras trong menu chính, sau đó chọn File system. Chọn thư mục
vừa tạo.