Đặt ngân sách hiệu năng trước khi thiết kế, đừng đợi tới lúc bị phàn nàn
Hiệu năng nếu bị coi là một giai đoạn tối ưu thì luôn thua tính năng. Nếu coi là ràng buộc được thống nhất trước khi thiết kế, nó lặng lẽ tạo ra những quyết định tốt hơn mà không tốn gì thêm.
Gần như đội ngũ nào cũng nói hiệu năng quan trọng. Và gần như đội ngũ nào cũng xếp nó vào một giai đoạn gần cuối, nơi nó cạnh tranh với việc kịp ra mắt và thua.
Những đội cuối cùng có sản phẩm nhanh làm một việc khác, và đó không phải tối ưu hoá anh hùng. Họ quyết định "đủ nhanh" nghĩa là gì trước khi ai đó mở phần mềm thiết kế, rồi đối xử với con số đó như cách họ đối xử với danh sách trình duyệt cần hỗ trợ: một ràng buộc, không phải một mục tiêu.
Vì sao "để sau tối ưu" thất bại
Ba lý do, và lý do thứ ba mới là thứ hạ gục bạn.
- Không có gì ép phải đánh đổi. Xét riêng lẻ, tính năng nào cũng đáng giá tiền của nó. Không có ngân sách thì không có gì nói "không", và tổng lại là chậm.
- Các cách sửa rẻ sẽ cạn. Nén, cache và định dạng ảnh chỉ mua cho bạn một lượng cố định và khiêm tốn. Sau đó bạn bước vào địa hạt kiến trúc.
- Nguyên nhân đắt đỏ đều mang tính kiến trúc. Một tầng dữ liệu lấy thừa, một luồng render chặn ở mạng, một script bên thứ ba nằm trong đường tới hạn. Chúng được quyết từ sớm và cực đắt để gỡ về sau.
Tới lúc bạn đo được, những quyết định định đoạt kết quả đã có tuổi đời vài tháng.
Một ngân sách trông như thế nào
Ngân sách là vài giới hạn cụ thể mà một bản build có thể đạt hoặc trượt. Ngân sách của chúng tôi cho phần tra cứu của KoiSpeak, làm ví dụ:
| Chỉ số | Ngân sách | Vì sao |
|---|---|---|
| Thời gian tới kết quả đầu tiên | Dưới 150 ms | Người ta mở từ điển giữa câu nói. Trên mức này là cảm giác phải chờ. |
| Largest Contentful Paint | Dưới 2,5 s trên điện thoại tầm trung | Ngưỡng phổ biến cho mức "tốt". |
| Interaction to Next Paint | Dưới 200 ms | Gõ phím không bao giờ được thấy giật. |
| Lượng JavaScript gửi đi | Trần cứng, đặt theo từng route | Con số duy nhất dự báo được các con số còn lại. |
Hai tính chất khiến ngân sách là thật chứ không phải trang trí:
- Nó là con số, không phải tính từ. "Nhanh" không làm build trượt được. 150 ms thì có.
- Nó được đo trên thiết bị người dùng của bạn đang có. Ngân sách đo trên laptop của lập trình viên qua wifi văn phòng thì không đo gì cả.
Kiểm thử trên phần cứng có thật
Đây là nơi phần lớn công việc hiệu năng đi chệch ngay từ trước khi bắt đầu.
Phát triển diễn ra trên máy nhanh, mạng nhanh. Người dùng của bạn ở trên điện thoại Android tầm trung, vài năm tuổi, dùng dữ liệu di động, với hàng chục ứng dụng chạy nền. Khoảng cách giữa hai trải nghiệm đó không phải 20%. Với các tác vụ nặng CPU, nó thường xuyên là 5 đến 10 lần.
Mức tối thiểu trên thực tế:
- Giữ một máy tầm trung thật trên bàn và dùng nó hằng tuần.
- Bật giới hạn CPU trong dev tools theo mặc định, không phải như một bài tập đặc biệt.
- Thu thập dữ liệu thực địa từ phiên dùng thật, không chỉ số liệu phòng lab. Lab cho biết cái gì đã đổi; thực địa cho biết người dùng thật sự nhận được gì.
Ngân sách thay đổi quyết định ra sao
Giá trị không nằm ở việc đo. Nó nằm ở những tranh luận được giải quyết sớm, rẻ, trước khi có gì được xây.
- Một bộ font trở thành một khoản chi phí. Bốn độ đậm và hai họ font là một phần đáng kể của ngân sách mobile. Bạn chọn hai độ đậm thay thế, ngay lúc thiết kế, không cần drama.
- Một thư viện animation phải tự chứng minh so với đoạn CSS bạn sẽ tự viết.
- Analytics và widget chat bị tính vào. Script bên thứ ba thường là khoản lớn nhất, và không ai để ý vì không ai trong đội viết chúng.
- Hình dạng dữ liệu đi theo ngân sách. Nếu kết quả đầu tiên phải về trong 150 ms, bạn không thể tải một khối lớn rồi lọc phía client. Điều đó đẩy bạn tới chỉ mục tiền tố, vốn dĩ mới là câu trả lời đúng.
Điểm cuối chính là mô-típ. Ngân sách không làm bạn chậm lại; nó làm kiến trúc đúng lộ ra sớm hơn.
Việc hiệu năng làm sau khi ra mắt là một chiến dịch giải cứu. Hiệu năng được coi là ràng buộc từ đầu thì chỉ là thiết kế.
Thực thi mà không rườm rà
Một ngân sách không ai kiểm tra chỉ là một điều ước. Hãy giữ việc thực thi rẻ:
- Cho build trượt khi vượt kích thước bundle. Một dòng cấu hình CI, bắt được phần lớn hồi quy, không tốn gì để duy trì.
- Chạy audit tổng hợp trên mỗi pull request, cho hai ba route quan trọng nhất.
- Cảnh báo trên số liệu thực địa theo tuần, không phải theo từng commit. Dữ liệu người dùng thật rất nhiễu; hãy nhìn xu hướng.
- Xem lại ngân sách khi sản phẩm đổi. Ngân sách không thiêng liêng. Nâng nó một cách có chủ ý, có lý do, là ổn. Trôi qua nó trong im lặng thì không.
Tiêu ngân sách vào đâu
Ngân sách là chuyện phân bổ, không phải chuyện tối giản. Có những thứ xứng đáng với sức nặng của chúng:
- Đường tới hạn. Thứ người dùng đến để lấy phải tới trước, phần còn lại đợi được. Với từ điển là ô tìm kiếm và kết quả. Với cửa hàng là ảnh sản phẩm và giá.
- Tốc độ cảm nhận hơn tốc độ đo được. Hiện khung xương kết quả ngay lập tức thường tốt hơn việc làm phản hồi nhanh thêm 40 ms.
- Phản hồi tức thì khi nhập liệu. Phản hồi cho một lần gõ phím trong khoảng 100 ms được cảm nhận là tức thì. Quá khoảng 300 ms là người ta bắt đầu để ý.
Phần khó chịu
Một ngân sách thật nghĩa là phải nói không với những thứ xét riêng đều tốt. Đó chính là điều làm nó hiệu quả, và cũng là lý do các đội lặng lẽ từ bỏ ngân sách: lần đầu tiên nó chặn một tính năng ai đó muốn, nước đi dễ nhất là nâng ngân sách lên.
Kỷ luật không nằm ở lúc đặt ra con số. Nó nằm ở cuộc họp mà bạn giữ được con số đó.