Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Hiểu Statistical Means và Percentiles: Hướng dẫn Thực tế

Performance monitoring là phần quan trọng của việc chạy successful application. Một trong những cách cơ bản nhất để biết performance của cái gì đó là measure duration mỗi lần nó xảy ra và distill statistics từ đó.

Mean (Trung bình)

Mean hoặc average của collection values là khởi đầu tốt để xem cái gì đó behave tốt hay xấu. Nó được tính bằng cách sum tất cả values được consider và chia cho số occurrences.

Trong Ruby, việc tính mean response time trông như sau:

def mean(array) (array.sum.to_f / array.length).round(2) end durations = [1,2,3,4,5,6,7,8,9,0] mean(durations) #=> 4.5

Lưu ý: Trong ví dụ, để kết quả chính xác hơn khi chia, chúng ta cast total duration value thành Float. Nếu không, Ruby sẽ round down đến nearest Integer, trả về 4 thay vì.

Median (Trung vị)

Statistic hữu ích khác là median. Mặc dù nghe giống, có sự khác biệt giữa mean và median của collection values.

Median là value tách upper half của set từ lower half của set.

Với dataset có odd number of values, bạn lấy median bằng cách sort values trước, sau đó select middle number. Cho set có even number of values, sau khi sort, median sẽ là mean của hai middle numbers.

def median(array) sorted_array = array.sort length = sorted_array.length if length.odd? # Middle number for odd arrays sorted_array[length / 2] else # Mean of two middle numbers first_value = sorted_array[length / 2] second_value = sorted_array[length / 2 - 1] (first_value + second_value) / 2.to_f end end # Even array durations = [1,2,3,4,5,6,7,8,9,0] median(durations) #=> 4.5 # Odd array durations = [1,1,2,3,4,5,6,7,8,9,0] median(durations) #=> 4

Statistic này là cách tốt để xem có huge skew trong data hay long tail.

durations = [1,2,3,4,5,2000] median(durations) #=> 3.5 mean(durations) #=> 335.83

Mean cho durations trên sẽ là 335.83 vì single outlier 2000ms. Median, chỉ 3.5, chỉ ra có skew.

Bằng cách tính cả mean và median của dataset, bạn có thể figure out có large outliers hay long tail không.

Vấn đề với Mean

Mặc dù mean và median là good indicators của performance, chúng không kể whole story. Nếu bạn request webpage mười lần, mean có thể rất thấp, nhưng một hoặc nhiều request vẫn có thể mất rất lâu để complete.

Hình ảnh dưới show 99th (blue) và 90th (green) percentiles và mean (red) cho action nhất định trong AppSignal. Bạn thấy 99th và 90th khá xa mean và có spikes. Nghĩa là trong khi average customer có good experience, thỉnh thoảng có user phải wait gần gấp đôi để page render. Idealy, bạn muốn tất cả values gần nhau nhất có thể, tạo consistent experience cho tất cả users.

Ví dụ, given duration set sau nơi 10 customer request page với duration giữa 100ms và 1 giây.

[100,100,100,100,100,100,100,100,100,1_000]

Điều này cho mean chỉ 190ms trong khi một user có very bad experience 1 second response time. Khi chỉ track mean, dễ nghĩ website great performance, thực tế thỉnh thoảng user có terrible experience.

Ví dụ trên chỉ cho 10 requests, nhưng tưởng tượng nếu bạn có ngàn request mỗi ngày, nghĩa là trăm user có terrible experience.

Percentiles (Phân vị)

Để give better idea về distribution của values, chúng ta dùng percentiles. Percentiles tương tự median - number chỉ point trong dataset nơi half set below number và half above. Percentiles tương tự vì 20th percentile nghĩa 20% numbers trong dataset below number đó.

Given sorted set sau:

[100,100,200,200,300,300,400,400,500,5_000]

Nếu muốn biết 20th percentile, tính như sau: Có 10 values trong set. Wanted value tại position 1 (20.0 / 100 * 10 - 1) vì arrays bắt đầu từ zero. Vì array chứa even items, chúng ta tính mean giữa index (2) và index + 1 (3). Kết quả 150 cho 20th percentile.

Ruby implementation naive trông như sau:

def percentile(array, wanted_percentile) sorted_array = array.sort index = (wanted_percentile.to_f / 100) * sorted_array.length - 1 # Check if index is not a round number if index != index.to_i sorted_array.at(index.ceil) elsif sorted_array.length.even? first_value = sorted_array.at(index) second_value = sorted_array.at(index + 1) (first_value + second_value) / 2 else sorted_array.at(index) end end # Array with odd amount of numbers durations = [100,200,200,300,300,400,400,500,5_000] percentile(durations, 20) #=> 100 percentile(durations, 90) #=> 500 percentile(durations, 95) #=> 5000, index is a fraction, 9.5 the rounded index is 10 # Array with even amount of numbers durations = [100,100,200,200,300,300,400,400,500,5_000] percentile(durations, 20) #=> 150, average of index 1 & 2 `(100 + 200) / 2` percentile(durations, 90) #=> 2750, average of index 8 & 9 `(500 + 5000) / 2 percentile(durations, 95) #=> 500, index is a fraction, 8.55 the index is 9

Function percentile này trông rất giống median calculation và thực tế median giống 50th percentile.

durations = [1,2,3] percentile(durations, 50) == median(durations) #=> true

AppSignal dùng statistics trên generate performance metrics cho Application. Chúng ta không chỉ rely mean/average mà tính 90th và 95th percentiles show outliers give better idea về distribution của requests. Tìm hiểu thêm trên performance tour page.

Oddities (Đặc điểm lạ)

Vì cách percentiles và averages được tính, đôi khi 90th percentile dip below mean, ví dụ given dataset:

durations = [1,1,1,1,1,1,1,1,1,1,2000] percentile(durations, 90) #=> 1 mean(durations) #=> 182.73

Điều này cho mean 182.73, và 90th percentile chỉ 1.

Nếu metric collection system chỉ show 90th percentile và mean, bạn vẫn deduce huge outlier trong dataset nếu 90th percentile drop below average.

👋 Nếu bạn like bài này, chúng ta viết nhiều hơn về Ruby (on Rails) performance, check out Ruby performance monitoring checklist.

Bạn Gần Đạt 100% Bài Viết Này

Đó là nó cho bây giờ! Trong bài khác, chúng ta sẽ nói về cách efficiently store và calculate percentiles cho tất cả requests của customer dùng Quantiles. Nếu có questions hoặc remarks về statistics và APMs, error tracking hoặc performance monitoring, hit chúng tôi up on Twitter @AppSignal hoặc via email.