Thấy nhiều bác chia sẻ những bài benchmark kinh nghiệm rất thực tế nhưng có vẻ chưa có bài nào nói rõ về các con số p50, p70, p80, p90, p95, p99,…

Cái này để hiểu thì AI phút mốt là ra, nhưng những kinh nghiệm thực tế ứng dụng nó ra sao, lúc nào, đo cái gì, làm sao kết quả tránh ảo,… Nên tôi mới nghĩ viết bài này, hiện tôi cũng đang làm bài benchmark chia sẻ tới mọi người ngâm cũng đã lâu.
p50/p90/p95/p99… là gì?
Đây là percentile (bách phân vị) của một tập dữ liệu đo được (thường là latency).
- p50: 50% mẫu ≤ giá trị này (median)
- p90: 90% mẫu ≤ giá trị này
- p95: 95% mẫu ≤ giá trị này
- p99: 99% mẫu ≤ giá trị này
- p99.9: 99.9% mẫu ≤ giá trị này (tức là chỉ khoảng 0.1% trường hợp chậm hơn mức này)
Ví dụ nhanh: nếu p95 = 300ms, thì 95% request ≤ 300ms, còn 5% request > 300ms.
Tại sao mọi người thấy p70/p80 nhưng tôi không liệt kê?
Nếu mới tìm hiểu thì chắc không tránh sai lầm khi ôm cả những con số này vào và làm bài toán có thể đi lệch hơn mà chưa chắc cần thiết đó chính là điều tôi nghĩ sẽ tiết kiệm thời gian cho mọi người vì gần như bạn không hỏi AI sẽ không trả lời.
Về cơ bản thì vẫn dùng được nhưng thực tế ngành hay chuẩn hoá quanh p50 + p90/p95 + p99 (và đôi khi p99.9). Vì bộ này cho bạn thấy đồng thời:
- Thường thì nhanh cỡ nào (p50)
- Đa số người dùng thấy thế nào (p90/p95)
- Các trường hợp chậm bất thường nặng đến đâu (p99/p99.9)
Vì sao benchmark thường chọn percentile thay vì average?
Average (trung bình) tuy Full HD nhưng có che sự thật. Hệ thống có thể:
- Đa số request rất nhanh
- Nhưng thỉnh thoảng có request rất chậm (do cache miss, DB bị kẹt, GC, mạng chập chờn…)
Người dùng thường bực vì những lần chậm bất thường, nên DevOps/SRE quan tâm:
- p50: trải nghiệm thường gặp
- p95: trải nghiệm đa số người dùng gặp
- p99/p99.9: các lần chậm bất thường (ít gặp hơn nhưng dễ gây timeout/retry, làm mọi thứ chậm theo). Trong đó p99.9 gắt hơn p99 vì nó soi vào phần cực hiếm nhưng cực tệ (hay gặp chính là mấy cam kết uptime 99,9% đó :)))
Nói ngắn gọn:
- Average trả lời trung bình ra sao
- Percentile trả lời phần lớn người dùng thấy ra sao, và lúc xấu thì xấu đến mức nào.
Benchmark đo cái gì cho đúng?
Latency
Bạn cần xác định mình đang đo latency kiểu nào, vì cùng là latency nhưng ý nghĩa khác nhau:
-
End-to-end (từ phía người gọi): Từ lúc client gửi request -> nhận response.
- Đúng với trải nghiệm thực tế.
- Bị ảnh hưởng bởi mạng và vị trí máy tạo tải.
-
Server-side (chỉ tính trong service): Thời gian xử lý bên trong service (không tính mạng).
- Tốt để tối ưu code/DB.
- Có thể bỏ sót chuyện đợi xếp hàng” hoặc vấn đề mạng.
-
Thời gian đợi vs thời gian xử lý
- Nhiều lúc chậm là do request đợi tới lượt, không phải do xử lý lâu.
- Nếu p95 tăng mạnh khi tải tăng, thường là đợi nhiều hơn.
Gợi ý thực tế: benchmark chuyên nghiệp thường ghi đồng thời:
- Latency end-to-end
- Ltency bên trong service
- Thời gian DB/cache/external API
- Thời gian đợi trước khi được xử lý (nếu có)
- Và nếu hệ thống yêu cầu rất cao, có thể theo dõi thêm p99.9 để bắt các lần siêu hiếm nhưng siêu chậm.
Throughput + Error (đi kèm bắt buộc)
Percentile đẹp mà lỗi cao là benchmark không dùng được.
- RPS/throughput
- Error rate (5xx/timeouts)
- Retry count (retry có thể làm kết quả nhìn ảo)
Saturation (để giải thích vì sao)
Nhìn thêm để biết tại sao chậm:
- CPU, memory, GC
- DB connections, thread pool, queue depth
- IO wait, network RTT/loss
- Cache hit rate
Theo tôi, benchmark tốt là benchmark giải thích được nguyên nhân, không chỉ nêu con số.
Những usecase thực tế áp dụng Percentile
Cũng có những đúc kết về các usecase thực tế mà tôi đã làm qua hầu như các bài benchmark sẽ gặp và lướt DevOps VietNam của chúng ta thấy nhiều bác chia sẻ rất hữu ích nên cũng muốn góp công sức.
Use case 1: Benchmark API/service khi đổi code hoặc infra
- Mục tiêu: Bản mới có chậm hơn bản cũ không, ở mức tải X?
Cách làm chuẩn (dựa vào kinh nghiệm của tôi):
- Chạy cùng workload, cùng kiểu tạo tải
- So sánh p50/p90/p95/p99 (và p99.9 nếu cần) + throughput + error
- Nếu p95 tăng mà p50 không tăng thì thường là có vấn đề ở rare path/tail path (ví dụ cache miss, GC, lock contention…)
Ví dụ:
- v1: p50 40ms, p95 120ms, p99 250ms
-
v2: p50 42ms, p95 160ms, p99 600ms
=> Majority vẫn ổn, nhưng tail latency tệ hơn nhiều thì rủi ro timeout/retry cao hơn. Nếu hệ thống cực nhạy, bạn sẽ soi thêm p99.9 để biết extreme tail có đang tệ quá không.
Use case 2: SLO/SLA thực dụng
SLO hay gặp: 95% request < 200ms hoặc 99% < 500ms. Với hệ thống yêu cầu rất cao, đôi khi sẽ có mục tiêu dạng 99.9% < X.
Percentile biến thành cam kết chất lượng:
- p95: cam kết cho majority
- p99: kiểm soát tail
- p99.9: kiểm soát extreme tail (thường gặp ở hệ thống đòi hỏi ổn định cao)
Use case 3: CI/CD & DevOps flow (build/test/deploy time)
Không chỉ latency HTTP. Percentile dùng tốt cho:
- p90 build time, ví dụ kết quả như là 90% build xong trong 12 phút
- p95 deploy lead time, ví dụ kết quả như là hầu hết deploy không vượt 20 phút
Điểm hay: nó giúp tìm sporadic slowdown (cache miss, cold runner, dependency fetch chậm…). Với CI/CD, p99.9 thường ít dùng hơn vì cần rất nhiều mẫu và giá trị thực tiễn không phải lúc nào cũng cao (và thật sự cũng chưa chắc quá cần thiết, chắc mấy big4 sẽ khai thác)
Use case 4: Batch/job processing
- p95 runtime: majority job ổn
- p99 runtime: tail jobs kéo dài, dễ làm vỡ deadline/backlog tăng
- p99.9 (nếu job cực nhiều và cần kiểm soát extreme tail): bắt các job cực kỳ hiếm nhưng cực kỳ lâu.
Cách benchmark percentile như thế nào (thực tế hay sai ở đây)?
Đủ mẫu cho percentile bạn quan tâm
- p99 nghĩa là xét 1% chậm nhất nên nếu bạn chỉ chạy ít request, con số này sẽ dao động mạnh.
- p99.9 còn khó hơn vì nó xét 0.1% chậm nhất nên cần rất nhiều samples (hoặc nhiều lần chạy) thì mới đáng tin.
- Muốn nói p99/p99.9 đáng tin, thường cần nhiều samples hoặc chạy nhiều lần.
Đây là yếu tố cực kỳ quan trọng mà nhiều cam kết bạn hay thấy và cũng là một bài benchmark rất mất công.
Tách giai đoạn khởi động
Hệ thống thường có giai đoạn đầu:
-
Warm cache, warm connection, autoscale… Nếu trộn vào kết quả, percentile sẽ bị méo.
Thực hành hay dùng:
- Chạy một đoạn warm-up
- Chỉ lấy số liệu trong đoạn steady-state
Chọn kiểu tạo tải phù hợp
Nếu bạn giữ cố định số người gọi cùng lúc (concurrency cố định), khi hệ thống chậm nó sẽ tự giảm tốc độ gọi. Đây là hiệu ứng closed-loop load generation (dễ làm latency nhìn đẹp hơn).
Nếu bạn giữ cố định số request đến mỗi giây (RPS cố định), rõ ràng nó sẽ phản ánh thật hơn khi traffic đến đều (gần với open-loop).
Không trộn nhiều loại request vào chung
Đừng gộp nhiều endpoint/payload khác nhau vào cùng một p95 rồi kết luận.
Benchmark nên tách theo:
- Endpoint
- Loại request
- Cache hit/miss (nếu có)
Tránh lấy percentile của percentile
Thêm cái sai hay gặp nữa là tính p95 theo từng phút, rồi lại lấy p95 của các p95 đó. Kết quả rất dễ lệch. Tốt nhất là tính percentile từ dữ liệu gốc (hoặc histogram chuẩn) trong đúng khoảng thời gian benchmark.
Nên nhìn bộ percentile nào?
Một bộ hay dùng khi benchmark service:
- p50: median latency
- p90/p95: high-percentile latency cho majority traffic
- p99: tail latency
- p99.9: extreme tail latency (khi hệ thống rất nhạy và bạn cần kiểm soát cả trường hợp cực hiếm)
Mẫu report benchmark thực tế
Khi benchmark, report tốt thường có:
Bối cảnh
- Version, config, commit, loại máy/cluster, vùng đặt máy
- Dữ liệu lớn cỡ nào, cache đang nóng hay lạnh
- Tool tạo tải và chạy ở đâu
Cách chạy
- Tải đến theo kiểu nào (giữ RPS hay giữ concurrency)
- Tăng tải thế nào, chạy ổn định bao lâu
Kết quả
- Throughput + error rate + retries
- p50/p90/p95/p99 (và p99.9 nếu cần) (tách theo endpoint)
- CPU/mem/GC, DB pool, queue depth… (để giải thích)
Kết luận
- Chậm do xử lý lâu hay do phải đợi
- Thay đổi nào gây khác biệt (DB, cache, network…)
Case study thực tế
Phần này tôi viết thêm từ các note kinh nghiệm để mọi người càng hiểu sâu hiểu rõ hơn. Còn như ở trên chắc mọi người cũng rất hiểu và giải đáp được hầu hết các thắc mắc về các chỉ số cũng như ứng dụng thực tế rồi.
Latency budget và cách đọc p95/p99 theo budget
Thay vì chỉ nói p95 = bao nhiêu ms, hãy đặt mục tiêu dạng:
- p95 < X ms
- p99 < Y ms
- p99.9 < Z ms (nếu cần)
Và đi kèm câu giải thích 1 dòng, ví dụ:
- Trong 10,000 requests, khoảng 100 requests sẽ tệ hơn p99, khoảng 10 requests sẽ tệ hơn p99.9.
Như vậy sẽ giúp người đọc cảm được con số hơn (đặc biệt làm report cho sếp cho rõ ràng hoặc các nhân sự chưa có chuyên môn kỹ thuật)
Nguyên tắc kiềng ba chân
Kết quả benchmark nên luôn trình bày theo cụm:
- Throughput (RPS)
- Error rate (timeout/5xx)
- p50/p95/p99 (hoặc thêm p99.9)
Vì chỉ cần thiếu 1 cái là số liệu dễ bị đẹp giả (nói cho rõ không phải là để mọi người ép đáp số nhé :)))
Chọn percentile theo loại hệ thống (cực thực dụng)
- Web/API thông thường: p50 + p95 + p99
- User-facing cực nhạy (payment, realtime, trading): thêm p99.9
- Batch/worker: p95 + p99 (p50 ít quan trọng hơn)
- CI/CD: p90/p95 là đủ, p99.9 thường không cần
Cái này giúp mọi người đỡ chọn sai chỉ số nhé.
Golden signals để giải thích tại sao p99 xấu
Nếu p99/p99.9 xấu, 90% trường hợp thủ phạm rơi vào 1 trong các nhóm này:
- Saturation: CPU throttling, thread pool/connection pool cạn
- Downstream: DB/cache/external API chậm
- Queueing: backlog/queue depth tăng
- GC/Memory pressure
- Network: RTT/loss tăng
Lưu ý này mọi người hiểu thì sẽ dễ đi tìm nguyên nhân ở đâu hơn.
Kết luận nhanh benchmark
-
p50 ổn, p95 ổn, p99 xấu
- Kết luận: Phần lớn request chạy ổn, nhưng đuôi latency đang tệ hơn rõ rệt (thỉnh thoảng có vài request rất chậm). Khả năng cao do các hiện tượng xảy ra không đều như GC pause, lock contention, resource contention, hoặc downstream (DB/cache/external) thỉnh thoảng chậm.
-
p95 tăng theo load, throughput không tăng tương ứng
- Hệ thống bắt đầu vào vùng bão hoà (saturation). Khi tăng tải thì request bị tích hàng chờ (queueing) nhiều hơn nên p95 phình ra, nhưng throughput không tăng vì đã chạm giới hạn tài nguyên hoặc giới hạn xử lý.
-
Latency đẹp nhưng error/retry tăng
- Kết quả benchmark không đáng tin. Số đo latency nhìn đẹp có thể vì hệ thống fail nhanh (timeout/5xx sớm) hoặc client retry làm sai bức tranh thật. Cần xem lại cách đo và luôn đánh giá cùng với error rate, timeout và retry.
Đến đây mà chưa biết làm chưa biết report thì tôi cũng hết lực chia sẻ rồi…
Checklist mini để tránh benchmark sai
- Warm-up tách riêng
- Không trộn nhiều endpoint vào 1 percentile
- Cùng load profile và cùng dataset
- Luôn báo cáo retry + timeout
- p99.9 chỉ dùng khi có đủ samples
Cũng hết ruột gan rồi
Tôi đi làm lúc 5y exp mới bắt đầu có các task chính thức về benchmark hệ thống, và đến giờ cũng may mắn được qua khá nhiều bài toán. Nhưng mà có thể các bạn trẻ hơn làm trong các doanh nghiệp lớn hơn đã tiếp xúc bài toán này từ lúc còn 2-3-4 năm kinh nghiệm chẳng hạn. Có gì cần thiết, hữu ích tôi cũng đã chia sẻ rồi, cũng vì lĩnh ngộ tư tưởng các bác và các sếp tại DevOps VietNam để cùng lan toả giá trị phát triển cộng đồng. Mọi người làm thực tế có vấn đề gì cần trao đổi cứ bình luận nhé.







