Bài giảng Kỹ thuật lập trình - Chương 5: Tính chỉnh mã nguồn và xây dựng tài liệu chương trình - Vũ Thị Hương Giang
1.1. Hiệu năng
• Sau khi áp dụng các kỹ thuật xây dựng CT PM: • CT đã có tốc độ đủ nhanh
- Không nhất thiết phải quan tâm đến việc tối ưu hóa hiệu năng
Chỉ cần giữ cho CT đơn giản và dễ đọc
Hầu hết các thành phần của 1 CT có tốc độ đủ nhanh Thường chỉ một phần nhỏ làm cho CT chạy chậm
– Tối ưu hóa riêng phần này nếu cần
Các bước làm tăng hiệu năng thực hiện CT
- Tính toán thời gian thực hiện của các phần khác nhau trong
CT
– Xác định các "hot spots” – đoạn mã lệnh đòi hỏi nhiều thời gian thực hiện
– Tối ưu hóa phần CT đòi hỏi nhiều thời gian thực hiện
- Lặp lại các bước nếu cần
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Kỹ thuật lập trình - Chương 5: Tính chỉnh mã nguồn và xây dựng tài liệu chương trình - Vũ Thị Hương Giang", để tải tài liệu gốc về máy hãy click vào nút Download ở trên.
File đính kèm:
- bai_giang_ky_thuat_lap_trinh_chuong_5_tinh_chinh_ma_nguon_va.pdf
Nội dung text: Bài giảng Kỹ thuật lập trình - Chương 5: Tính chỉnh mã nguồn và xây dựng tài liệu chương trình - Vũ Thị Hương Giang
- CHƯƠNG V. TINH CHỈNH MÃ NGUỒN VÀ XÂY DỰNG TÀI LIỆU CHƯƠNG TRÌNH I. Tinh chỉnh mã nguồn II. Xây dựng tài liệu chương trình
- 1.1. Hiệu năng • Sau khi áp dụng các kỹ thuật xây dựng CT PM: • CT đã có tốc độ đủ nhanh – Không nhất thiết phải quan tâm đến viêc tối ưu hóa hiệu năng – Chỉ cần giữ cho CT đơn giản và dễ đọc • Hầu hết các thành phần của 1 CT có tốc độ đủ nhanh – Thường chỉ một phần nhỏ làm cho CT chạy chậm – Tối ưu hóa riêng phần này nếu cần • Các bước làm tăng hiệu năng thực hiện CT – Tính toán thời gian thực hiện của các phần khác nhau trong CT – Xác định các “hot spots” – đoạn mã lệnh đòi hỏi nhiều thời gian thực hiện – Tối ưu hóa phần CT đòi hỏi nhiều thời gian thực hiện – Lặp lại các bước nếu cần
- 1.2. Code tuning (tinh chỉnh mã nguồn) là gì ? • Thay đổi mã nguồn đã chạy thông theo hướng hiệu quả hơn nữa • Chỉ thay đổi ở phạm vi hẹp, ví dụ như chỉ liên quan đến 1 CTC, 1 tiến trình hay 1 đoạn mã nguồn • Không liên quan đến việc thay đổi thiết kế ở phạm vi rộng, nhưng có thể góp phần cải thiện hiệu năng cho từng phần trong thiết kế tổng quát
- 1.4. Quan hệ giữa hiệu năng và tinh chỉnh mã nguồn • Việc giảm thiểu số dòng lệnh viết bằng 1 NNLT bậc cao KHÔNG: – Làm tăng tốc độ chạy CT – làm giảm số lệnh viết bằng ngôn ngữ máy a[ 1 ] = 1 ; a[ 2 ] = 2 ; a[ 3 ] = 3 : a[ 4 ] = 4 ; for i = 1 to 10 do a[i] = i; a[ 5 ] = 5 ; a[ 6 ] = 6 ; a[ 7 ] = 7 ; a[ 8 ] = 8 ; a[ 9 ] = 9 ; a[ 10 ] = 10 ;
- Quan hệ giữa hiệu năng và tinh chỉnh mã nguồn • 1 số kỹ thuật viết mã hiệu quả được áp dụng để tinh chỉnh mã nguồn • Nhưng nhìn chung không nên vừa viết chương trình vừa tinh chỉnh mã nguồn – Không thể xác định được những nút thắt trong chương trình trước khi chạy thử toàn bộ chương trình – Việc xác định quá sớm các nút thắt trong chương trình sẽ gây ra các nút thắt mới khi chạy thử toàn bộ chương trình – Nếu vừa viết chương trình vừa tìm cách tối ưu mã nguồn, có thể làm sai lệch mục tiêu của chương trình
- 2.1. Tinh chỉnh các biểu thức logic • Không kiểm tra khi đã biết kết quả rồi – Initial code if ( 5 < x ) && ( x < 10 ) . – Tuned code if ( 5 < x ) if ( x < 10 ) .
- 2.1. Tinh chỉnh các biểu thức logic • Sắp xếp thứ tự các phép kiểm tra theo tần suất xảy ra kết quả đúng – Initial code Select inputCharacter Case "+", "=" ProcessMathSymbol( inputCharacter ) Case "0" To "9" ProcessDigit( inputCharacter ) Case ",", ".", ":", ";", "!", "?" ProcessPunctuation( inputCharacter ) Case " " ProcessSpace( inputCharacter ) Case "A" To "Z", "a" To "z" ProcessAlpha( inputCharacter ) Case Else ProcessError( inputCharacter ) End Select
- 2.1. Tinh chỉnh các biểu thức logic • Sắp xếp thứ tự các phép kiểm tra theo tần suất xảy ra kết quả đúng – Tuned code: chuyển lệnh switch thành các lệnh if - then - else
- 2.1. Tinh chỉnh các biểu thức logic • Thay thế các biểu thức logic phức tạp bằng bảng tìm kiếm kết quả Initial code if ( ( a && !c ) || ( a && b && c ) ) { category = 1; } else if ( ( b && !a ) || ( a && c && !b ) ) { category = 2; } else if ( c && !a && !b ) { category = 3; } else { category = 0; }
- 2.1. Tinh chỉnh các biểu thức logic • Lazy evaluation: 1 trong các kỹ thuật viết mã chương trình hiệu quả đã học
- 2.2. Tinh chỉnh các vòng lặp • Nếu các vòng lặp lồng nhau, đặt vòng lặp xử lý nhiều công việc hơn bên trong – Initial code for ( column = 0; column < 100; column++ ) { for ( row = 0; row < 5; row++ ) { sum = sum + table[ row ][ column ]; } } – Tuned code for (row = 0; row < 5; row++ ) { for (column = 0; column < 100; column++) { sum = sum + table[ row ][ column ]; } }
- 2.3. Tinh chỉnh việc biến đổi dữ liệu • Một số kỹ thuật viết mã hiệu quả đã học: – Sử dụng kiểu dữ liệu có kích thước nhỏ nếu có thể – Sử dụng mảng có số chiều nhỏ nhất có thể – Đem các phép toán trên mảng ra ngoài vòng lặp nếu có thể – Sử dụng các chỉ số phụ – Sử dụng biến trung gian
- 2.5. Tinh chỉnh dãy lệnh (đã học) • Sử dụng các hàm inline
- Giúp trình dịch làm tốt công việc của nó • Trình dịch có thể thực hiện 1 số thao tác tôi ưu hóa tự động – Cấp phát thanh ghi – Lựa chọn lệnh để thực hiện và thứ tự thực hiện lệnh – Loại bỏ 1 số dòng lệnh kém hiệu quả • Nhưng trình dịch không thể tự xác định – Các hiệu ứng phụ (side effect) của hàm hay biểu thức: ngoài việc trả ra kết quả, việc tính toán có làm thay đổi trạng thái hay có tương tác với các hàm/biểu thức khác hay không – Hiện tượng nhiều con trỏ trỏ đến cùng 1 vùng nhớ (memory aliasing) • Tinh chỉnh mã nguồn có thể giúp nâng cao hiệu năng – Chạy thử từng đoạn chương trình để xác định “hot spots” – Đọc lại phần mã viết bằng assembly do trình dịch sản sinh ra – Xem lại mã nguồn để giúp trình dịch làm tốt công việc của nó
- Kết luận • Hãy lập trình một cách thông minh, đừng quá cứng nhắc – Không cần tối ưu 1 chương trình đủ nhanh – Tối ưu hóa chương trình đúng lúc, đúng chỗ • Tăng tốc chương trình – Cấu trúc dữ liệu tốt hơn, giải thuật tốt hơn: hành vi tốt hơn – Các đoạn mã tối ưu: chỉ thay đổi ít • Các kỹ thuật tăng tốc chương trình – Tinh chỉnh mã nguồn theo hướng • Giúp đỡ trình dịch • Khai thác khả năng phần cứng
- Các loại tài liệu chương trình • Tài liệu trong (Internal documentation) – Các chú thích cho mã nguồn (comments) • Tài liệu ngoài (External documentation) – Dành cho các lập trình viên khác khi làm việc với mã nguồn • Tài liệu dành cho người sử dụng – Cẩm nang dành cho những người sử dụng mã nguồn
- Các cách chú thích cần tránh: chú thích vô nghĩa • Làm chủ ngôn ngữ – Hãy để chương trình tự diễn tả bản thân – Rồi • Viết chú thích để thêm thông tin i= i+1; /* Add one to i */ for (i= 0; i < 1000; i++) { /* Kha phuc tap */ . . Ở đây là vài trăm dòng lệnh khó hiểu, ko được chú thích. } int x,y,q3,z4; /* Dinh nghia vai bien */ int main() /* Chuong trinh chinh */ while (i < 7) {/* Khong co gi dac biet */}
- Các chú thích cần tránh: chú thích chỉ nhằm mục đích phân đoạn mã nguồn while (j < ARRAYLEN) { printf ("J is %d\n", j); for (i= 0; i < MAXLEN; i++) { /* These comments only */ for (k= 0; k < KPOS; k++) { /* Serve to break up */ printf ("%d %d\n",i,k); /* the program */ } /* And make the indentation */ } /* Very hard for the programmer to see */ j++; }
- Ví dụ: chú thích các đoạn mã nguồn #include #include int main(void) /* Doc vao ban kinh duong tron tu stdin, tinh duong kinh va chu vi, sau do ghi ra stdout. Neu thuc hien thanh cong thi tra ve ket qua 0. */ { const double PI = 3.14159; int radius; int diam; double circum; /* Doc vao ban kinh duong tron. */ printf("Enter the circle's radius:\n"); if (scanf("%d", &radius) != 1) { fprintf(stderr, "Error: Not a number\n"); exit(EXIT_FAILURE); /* or: return EXIT_FAILURE; */ }
- Những thành phần nào của mã nguồn bắt buộc phải có chú thích • Tất cả các file (nếu chương trình gồm nhiều file) đều cấn chú thích về nội dung của file đó • Tất cả các hàm: dùng để làm gì, dùng các biến đầu vào nào, trả ra cái gi. • Biến có tên không rõ ràng – i,j,k cho vòng lặp, FILE *fptr không cần chú thích – nhưng int total; cần • Tất cả các struct/typedef (trừ phi nó thực sự quá tầm thường)
- Chú thích hàm • Mô tả những gì cần thiết để gọi hàm 1 cách chính xác – Mô tả hàm làm gì, chứ không phải nó làm như thế nào – Bản thân mã nguồn phải rõ ràng, dễ hiểu để biết cách hàm làm việc – Nếu không, hãy viết chú thích bên trong định nghĩa hàm • Mô tả đầu vào: Tham số truyền vào, đọc file gì, biến tổng thể được dùng • Mô tả đầu ra: giá trị trả về, tham số truyền ra, ghi ra files gì, các biến tổng thể mà nó tác động tới • Mô tả bẫy lỗi: có hay không việc bẫy lỗi
- Ví dụ: chú thích hàm • Good function comment /* decomment.c */ int main(void) { /* Đọc 1 CT C qua stdin. Ghi ra stdout với mỗi chú thích thay bằng 1 dấu cách. Trả về 0 nếu thành công, EXIT_FAILURE nếu không thành công. */ } – Describes what the function does
- 2. Tài liệu ngoài cho các LTV khác • Giới thiệu với các LTV khác mã nguồn dùng để làm gì • Nhiều công ty lớn tự đặt chuẩn riêng để viết tài liệu ngoài • Mục tiêu là cho phép các LTV khác sử dụng và thay đổi mã nguồn mà không cần đọc và hiểu từng dòng lệnh • Đừng quên viết tài liệu ngoài cho bài tập lớn
- Viết tài liệu ngoài: bước 2 • Miêu tả 1 cách tổng quát quy trình nghiệp vụ của CT – Có thể vẽ biểu đồ – Ví dụ: dùng flowchart • Giải thích các giải thuật phức tạp được sử dụng trong chương trình, hoặc cho biết có thể tìm được lời giải thích ở đâu – Ví dụ: "I use the vcomplexsort; see Knuth page 45 for more details"
- Viết tài liệu ngoài: bước 2 • Miêu tả các hàm chính trong CT – LTV tự quyết định hàm nào là hàm chính trong CT của mình – Xem xét hàm nào là hàm nghiệp vụ thực sự, ko nhất thiết phải là hàm dài nhất hay khó viết nhất • Miêu tả các tham số đầu vào và giá trị trả về
- Viết tài liệu cho người dùng • Thu thập các thông tin liên quan đến sản phẩm cần viết hướng dẫn sử dụng • Miêu tả sản phẩm • Miêu tả quy trình sử dụng từng chức năng của sản phẩm • Dùng thử sản phẩm theo các bước được miêu tả trong quy trình sử dụng