Áp dụng nguyên tắc 'đo lường trước khi tối ưu' như vòng lặp: baseline, phân tích, thay một điều, xác minh tác động, và xây thói quen hiệu suất điềm tĩnh hơn.

Công việc cải thiện hiệu suất thường cảm thấy ngẫu nhiên khi bạn bắt đầu bằng việc sửa. Hôm nay bạn nén file, hôm sau chỉnh cache, rồi lại bỏ một thư viện. Có lúc có tác dụng. Có lúc không thay đổi gì, và bạn không biết vì sao.
Rủi ro lớn nhất là tối ưu sai chỗ. Nếu trang chậm vì main thread bị chặn bởi JavaScript, dành hàng giờ nén ảnh có thể chẳng làm thay đổi gì đáng kể. Hoặc bạn có thể làm nhanh thứ người dùng không nhận ra, trong khi nguyên nhân thực sự là một cuộc gọi API lâu, một layout liên tục reflow, hoặc một script chặn.
Cũng có cái bẫy khi đánh giá theo cảm nhận. “Cảm thấy nhanh hơn” có thể là placebo (ví dụ một spinner) hoặc do test ở mạng, thiết bị, hoặc thời điểm khác. “Thực sự nhanh hơn” nghĩa là cùng hành động, trong cùng điều kiện, cho ra số tốt hơn.
Một lời hứa đơn giản sửa phần lớn vấn đề này: đo trước khi tối ưu, rồi quyết định. Khi bạn coi hiệu suất như một bài toán đo lường, bạn ngừng đoán và bắt đầu học.
Vòng lặp thực tế trông như thế này: chọn một hành động người dùng để cải thiện, ghi baseline trong điều kiện có thể lặp lại, thay đổi một điều bạn có thể giải thích, rồi đo lại và chỉ giữ thay đổi nếu số liệu cải thiện.
Paul Irish là một trong những tiếng nói nổi bật về hiệu năng web. Qua công việc trên công cụ trình duyệt và hướng dẫn hiệu suất, ông giúp phổ biến một ý tưởng thẳng thắn: việc đầu tiên của bạn không phải đoán chỗ nào chậm, mà là chứng minh nó.
Tư duy này thay đổi động lực đội nhóm. Thay vì tranh luận theo thói quen như “luôn là ảnh gây ra” hay “chắc là framework,” bạn bắt đầu bằng bằng chứng. Khi bạn có thể chỉ vào một timeline, một truy vấn chậm, hoặc một long task, cuộc trò chuyện chuyển từ đổ lỗi sang sửa chữa.
“Đo trước khi tối ưu” cũng làm nguội các tranh luận vì nó tạo ra quy tắc chung: đồng ý về cái bạn đo, đồng ý về nghĩa của “tốt hơn”, và chỉ ăn mừng khi số liệu thay đổi.
Cách này hiệu quả cho site nhỏ và app lớn. Một baseline duy nhất có thể chặn các tối ưu vi mô ngẫu nhiên trên trang marketing. Trên sản phẩm lớn, đo lường nhất quán giữ cho hiệu suất không trở thành danh sách việc vặt vô tận.
Một cách đơn giản để hiện thực hóa là coi hiệu suất như một báo cáo lỗi: các bước rõ để tái hiện, chỉ số bạn thấy, và một thay đổi gắn với một kết quả. Nếu hai người không đồng ý, chạy lại đo và để dữ liệu quyết định.
Trước tiên hãy coi hiệu suất như bài toán quan trắc: thêm cách để quan sát trải nghiệm thực tế của người dùng. Nếu bạn không thấy nó, bạn sẽ tranh luận dựa trên ý kiến, chứ không phải bằng chứng. Đó là ý nghĩa thật sự của việc đo trước.
Quan trắc không cần cầu kỳ. Là việc thu thập vài tín hiệu một cách nhất quán, ở cùng vị trí, để bạn trả lời các câu hỏi cơ bản:
Bạn thường muốn hai loại dữ liệu.
Dữ liệu lab được ghi trong môi trường có kiểm soát: một laptop hoặc thiết bị thử cố định, profile mạng ổn định, cùng các bước mỗi lần. Nó tuyệt cho debug vì bạn có thể tái tạo chậm ngay khi cần.
Dữ liệu người dùng thực là thứ người ta trải nghiệm ngoài đời: thiết bị, vị trí, và chất lượng kết nối khác nhau. Nó tuyệt để ưu tiên vì cho thấy điều gì ảnh hưởng đến người dùng thực, không chỉ một lần test.
Dù không phải chuyên gia, bạn vẫn có thể đo các mốc tải trang (như nội dung đầu tiên hiển thị), long tasks và chặn main-thread, request mạng chậm, công việc render tốn kém (layout, style, paint), và thời gian phản hồi server.
Những tín hiệu này thường sống ở vài nơi: DevTools cho profiling lab, log và trace server cho thời gian backend, và analytics hoặc dashboard RUM cho dữ liệu người dùng thực. Ví dụ, nếu trang thanh toán cảm thấy chậm, DevTools có thể cho thấy trình duyệt bận render UI giỏ hàng lớn trong khi log server cho thấy API nhanh. Nếu không có quan trắc, bạn có thể tối ưu backend mà chẳng bao giờ sửa được vấn đề thực sự.
Để đo trước khi tối ưu, bạn cần một điểm bắt đầu tin cậy. Baseline là cùng một hành động, đo cùng cách, trong cùng điều kiện.
Bắt đầu với một hành trình người dùng thật, không phải “toàn bộ site.” Chọn thứ bạn mô tả trong một câu, như “mở trang chủ và cuộn đến lưới sản phẩm đầu tiên” hoặc “đăng nhập và đến dashboard.” Giữ hẹp giúp số liệu ổn định hơn và bước tiếp theo rõ ràng.
Tiếp theo, chọn 1 đến 3 chỉ số phù hợp với hành trình. Với một lượt xem trang, cặp phổ biến là LCP (nội dung chính xuất hiện nhanh thế nào) và TTFB (server phản hồi nhanh thế nào). Với flow như thanh toán, bạn có thể theo dõi thời gian hoàn tất bước 1 và thời gian phản hồi API cho cuộc gọi thanh toán. Quá nhiều chỉ số khiến dễ chọn lọc.
Viết xuống thiết lập test để người khác có thể tái hiện sau. Khác biệt nhỏ có thể đổi kết quả:
Cuối cùng, xác định “đủ tốt” cho đối tượng của bạn. Ví dụ: “LCP dưới 2.5s trên điện thoại tầm trung, trên 4G.” Nếu bạn dùng Koder.ai, chụp một snapshot trước khi test giúp gắn baseline vào một phiên bản đã biết.
Trước khi profiling, hãy khiến vấn đề xảy ra lại theo yêu cầu. Nếu không tái hiện được, bạn không thể tin kết quả.
Bắt đầu từ điều người dùng cảm thấy, không phải giả định của bạn. Là render đầu tiên chậm? Nhấp bị treo trước khi gì thay đổi? Chờ lâu sau khi nộp form? Chọn khoảnh khắc người dùng phàn nàn và tập trung vào đó.
Chạy nhanh một lần để xác nhận chậm là có thật và có thể lặp lại. Giữ mọi thứ khác y hệt: cùng trang, cùng thiết bị, cùng mạng nếu được. Rồi ghi lại trigger và điểm chính xác nó chậm, như “sau khi nhấn Pay, nút bị đóng băng 1 giây” hoặc “cuộn giật khi danh sách sản phẩm xuất hiện.”
Một cách đơn giản để giữ lặp lại là một script nhỏ: mở trang từ tab mới, làm hành động gây lag, ghi điểm chính xác nó chậm, rồi lặp một lần để xác nhận.
Chụp 1–2 bản ghi baseline, không cần hàng chục. Bạn chỉ cần đủ bằng chứng để nói, “Có, sự chậm xảy ra, và nó xảy ra ngay chỗ này.”
Khi bạn có thể tái tạo chậm, dừng đoán mò. Mở profiler (với hầu hết mọi người là tab Performance của trình duyệt) và ghi một lần chạy của tương tác chậm. Mục tiêu không phải tìm mọi vấn đề, mà là biết thời gian đi đâu.
Bắt đầu với khối thời gian lớn nhất. Nhóm nhỏ hiếm khi giải thích một độ trễ rõ ràng một mình.
Một cách hữu dụng để đọc bản ghi là gom thời gian vào vài nhóm: mạng và tải (chờ request), scripting trên main thread (long JavaScript tasks), rendering và paint (layout và style), khoảng thời gian chờ (idle), và công việc lặp lại (bước tốn kém lặp lại nhiều lần).
Sai lầm phổ biến là nhầm lẫn server chậm với client chậm. Nếu timeline cho thấy nhiều khe dài khi request đang chờ, nút cổ chai có thể là mạng hoặc backend. Nếu nó cho thấy các nhiệm vụ dài trên main thread, bạn có vấn đề frontend dù mạng nhanh.
Trước khi thay đổi gì, viết một giả thuyết ngắn, có thể kiểm thử, dựa trên những gì bạn thấy. Ví dụ: “Trang chậm vì main thread bị chặn do phân tích JSON ngay sau khi API trả về.” Câu đó chuẩn bị cho bước tiếp theo.
Khi đã xác định nút cổ chai, kiềm chế ham muốn “sửa mọi thứ.” Thay đổi một biến để bạn nối được nhân quả.
Giữ thay đổi nhỏ và dễ hoàn tác. Việc viết lại lớn làm mờ kết quả: nếu nhanh hơn, bạn sẽ không biết vì sao. Nếu tệ hơn, rollback rủi ro.
Các thay đổi một-thứ tốt là cụ thể và có thể kiểm thử. Ví dụ: trì hoãn hoặc loại bỏ một script bên thứ ba chặn render, nén một ảnh quá lớn trên trang chậm, thêm cache cho một truy vấn DB tốn kém, tách một component UI nặng để render ít hơn lúc đầu, hoặc giảm công việc trong một vòng lặp nóng bạn thấy trong profiler.
Trước khi động tới code, viết xuống bạn đã thay gì, tại sao chọn nó, và bạn mong gì sẽ cải thiện (ví dụ “giảm thời gian main-thread” hay “cắt thời gian DB một nửa”).
Nếu đội bạn dùng nền tảng hỗ trợ snapshot và rollback (như Koder.ai), chụp snapshot ngay trước thay đổi để “nhỏ và có thể hoàn tác” trở thành thực tế, không chỉ là hy vọng.
Bạn đã thay một thứ. Bây giờ chứng minh nó có ích.
Chạy lại cùng thiết lập test như baseline: cùng thiết bị, cùng phiên bản trình duyệt, cùng route và flow, cùng số lần chạy. So sánh trước vs sau dùng cùng các chỉ số. Đừng thêm chỉ số mới giữa chừng chỉ vì chúng trông tốt hơn.
Nhiễu là lý do phổ biến nhất khiến đội tranh cãi về hiệu suất. Để ý cache lạnh vs nóng, extension hoặc tiến trình nền, điều kiện mạng khác, VPN, biến động server (phút vắng so với phút đông), và khác biệt giữa “ngay sau deploy” và trạng thái ổn định.
Nếu median cải thiện nhưng worst-case tệ hơn, đó là một trao đổi thực tế. Quyết định cái gì quan trọng với người dùng, rồi ghi lại quyết định: giữ thay đổi, revert, hoặc viết giả thuyết mới và test lại.
Công việc hiệu suất trở nên rối khi bạn đo sai thứ hoặc thay quá nhiều cùng lúc. Bạn có thể tiêu tốn nhiều công sức mà không có chiến thắng rõ ràng, dù app có tiến bộ.
Một sai lầm là coi một điểm số duy nhất là mục tiêu. Điểm số có thể hữu ích, nhưng người dùng không trải nghiệm “một con số 92.” Họ trải nghiệm “trang hiện nội dung trong 2 giây” hoặc “nhấn Mua phản hồi ngay lập tức.” Chọn một kết quả mà người dùng thấy và đo nó liên tục.
Bẫy khác là chỉ test trên laptop mạnh. Nhiều chỗ chậm xuất hiện trên điện thoại tầm trung, mạng yếu, hoặc khi CPU bận. Nếu bạn chỉ profiling trên thiết bị tốt nhất, bạn có thể bỏ lỡ nút cổ chai.
Sự bối rối thường đến từ các mô hình như tối ưu thứ dễ thay vì thứ tốn nhiều thời gian, gộp nhiều tinh chỉnh vào một thay đổi, đổi đường dẫn test mỗi lần, bỏ re-test vì “cảm thấy nhanh hơn”, hoặc tự nhận thắng mà không chạy lại baseline.
Nếu bạn xây app với nền tảng chat-driven như Koder.ai, kỷ luật vẫn là: một thay đổi, rồi xác minh trên cùng flow để bạn tin kết quả.
Nếu chỉ giữ một thói quen, hãy giữ: đo trước khi tối ưu. Mục tiêu không phải dữ liệu vô tận. Mà là một vòng lặp có thể lặp mà bạn tin cậy.
Đặt tên chính xác cho hành trình người dùng bạn quan tâm. “Homepage chậm” là mơ hồ. “Từ trang sản phẩm đến nhấn Mua đến thấy màn hình xác nhận” cho bạn một kịch bản có thể lặp.
Dùng checklist này:
Phiên bản điềm tĩnh của công việc hiệu suất đơn giản: một đường dẫn, một thiết lập, một thay đổi, một kết quả được xác minh.
Phàn nàn hay gặp: thanh toán cảm thấy chậm ngay sau khi khách nhấn “Pay.” Mọi người bắt đầu đoán (ảnh, font, nút). Thay vào đó, coi nó như một test có thể lặp.
Thiết lập baseline có thể chạy lại. Chọn một thiết bị và một đường dẫn (cart → checkout → Pay → confirmation). Bật throttling mạng (ví dụ Fast 3G) và giữ nó y hệt mỗi lần. Đo một số đơn giản: thời gian từ nhấn “Pay” đến khi thấy màn hình xác nhận.
Rồi profile ngay khoảnh khắc đó và xem thời gian đi đâu. Thông thường bạn đang quyết giữa ba nhóm: mạng (request dài hoặc quá nhiều request), server (cuộc gọi thanh toán chậm ngay cả khi trình duyệt rảnh), hoặc main thread (trình duyệt bận chạy JavaScript và không thể cập nhật UI).
Giả sử profile cho thấy sau khi nhấn “Pay,” trình duyệt gửi một request analytics và gọi script kiểm tra gian lận, và request thanh toán phải chờ phía sau chúng. Đó không phải vấn đề “làm mọi thứ nhanh hơn.” Là một bước chặn duy nhất.
Thay một thứ có chủ ý. Ví dụ, khởi động request thanh toán ngay lập tức, và gửi analytics chỉ sau khi màn hình xác nhận hiện.
Xác minh với cùng thiết lập: cùng throttling, cùng các bước, nhiều lần chạy. Nếu thời gian xác nhận giảm và lỗi không tăng, bạn đã có chiến thắng thực. Cũng kiểm tra nhanh xem bạn không làm hỏng hoàn tiền, retry, hoặc cơ chế chống submit đôi.
Hiệu suất giữ ổn định khi đó là một thói quen, không phải một chiến dịch cứu vãn. Hãy mặc định là đo, ngay cả khi mọi thứ có vẻ ổn.
Chọn một tập nhỏ các chỉ số đội bạn sẽ luôn theo dõi. Giữ nhất quán để xu hướng dễ nhìn:
Xây một vòng lặp quanh các chỉ số đó. Kiểm tra baseline hàng tuần thường đủ. Khi một chỉ số trôi, đó là dấu để tái tạo chậm, profile, thay một thứ, và xác minh tác động.
Giữ nhật ký hiệu suất đơn giản theo định dạng đội bạn thực sự dùng. Ghi những gì bạn đo (bao gồm thiết bị, mạng và build), bạn đã thay gì, và số liệu thay đổi ra sao sau đó.
Nếu bạn xây với Koder.ai, Planning Mode có thể giúp bạn viết hành trình người dùng và chỉ số bạn quan tâm trước khi thay đổi gì. Rồi dùng snapshot và rollback để giữ thí nghiệm an toàn: chụp snapshot, áp một thay đổi, test lại, và rollback nếu kết quả nhiễu hoặc xấu hơn.
Trong lập kế hoạch hay review, một câu hỏi giữ văn hóa lành mạnh: “Chúng ta đã đo gì, và nó thay đổi ra sao?”
Bởi vì bạn rất dễ tiêu tốn hàng giờ để cải thiện thứ không phải là nguyên nhân gây chậm. Hãy bắt đầu bằng việc chứng minh thời gian đi đâu (mạng, server, main thread, hay rendering), rồi nhắm vào nút cổ chai lớn nhất.
Ghi lại một hành động cụ thể và các điều kiện chính xác, rồi lặp lại nó:
Nếu không thể lặp lại, bạn không thể tin kết quả.
Chọn 1–3 chỉ số phù hợp với điều người dùng cảm nhận:
Dữ liệu lab là phép đo trong môi trường có kiểm soát và có thể lặp lại (tốt để gỡ lỗi). Dữ liệu người dùng thực tế phản ánh thiết bị và mạng thật (tốt để ưu tiên).
Quy tắc hữu dụng: dùng dữ liệu người dùng thực để tìm những hành trình tệ nhất, rồi dùng lab profiling để giải thích tại sao nó chậm và thử sửa an toàn.
Đối xử như một bug report:
Điều này chuyển cuộc tranh luận từ ý kiến (“chắc là do ảnh”) sang bằng chứng.
Ghi lại tương tác chậm trong profiler và tìm khối thời gian lớn nhất:
Rồi viết một giả thuyết một câu để thử.
Nó giữ mối quan hệ nhân quả rõ ràng. Nếu bạn thay 5 thứ cùng lúc và trang nhanh hơn, bạn không biết cái nào có tác dụng. Nếu chậm hơn, rollback sẽ rắc rối.
Quy tắc thực tế: một thay đổi bạn có thể giải thích, một chỉ số bạn mong thay đổi, rồi đo lại.
Dùng cùng thiết lập test và so sánh trước/sau bằng cùng chỉ số.
Để giảm nhiễu:
Chỉ giữ thay đổi nếu số liệu cải thiện trong cùng điều kiện.
Những bẫy phổ biến:
Giữ một hành trình, một thiết lập, một kết quả được xác minh.
Dùng chúng để làm cho thí nghiệm an toàn và có thể so sánh:
Công cụ giúp, nhưng chiến thắng thực sự là vòng lặp có thể lặp: baseline → profile → thay đổi → xác minh.
Tránh theo dõi quá nhiều số cùng lúc kẻo dễ chọn lọc theo ý muốn.