Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เข้าใจ Statistical Means และ Percentiles: คู่มือปฏิบัติจริง

Performance monitoring 是運行 successful application 的重要部分 告訴 something performance 好壞的最基本方法之一 是每次發生時測量 duration 並從中提取統計數據

Mean

一組值的 mean 或 average 是查看某事物表現好壞的好起點 它通過將考慮的所有值相加然後除以發生次數來計算

在 Ruby 中 計算 mean response time 看起來像這樣:

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

Note: 在例子中 為了更準確的結果當除以時 我們將總 duration value cast 為 Float 否則 Ruby 會向下取整到最近的 Integer 返回 4 而不是

Median

另一個有用的統計數據是 median 雖然聽起來相似 但一組值的 mean 和 median 有區別

Median 是將一組的上半部分與下半部分分開的值

對於奇數個值的數據集 你通過先排序值然後選擇中間數字來獲得 median 對於偶數個值的集合 排序後 median 將是兩個中間數字的 mean

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

這個統計數據是查看數據是否有 huge skew 或 long tail 的好方法

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

上面 durations 的 mean 將是 335.83 因為單一 outlier 2000ms Median 只有 3.5 指出有 skew

通過計算數據集的 mean 和 median 你可以找出是否有任何大 outliers 或 long tail

The Problem with Mean

雖然 mean 和 median 是 performance 的好指標 它們不講完整的故事 如果你請求一個網頁十次 mean 可能非常低 但一個或多個請求仍然可能花費很長時間完成

下面的圖片顯示 AppSignal 中某個 action 的 99th (藍色) 和 90th (綠色) percentiles 和 mean (紅色) 你可以看到 99th 和 90th 相距 mean 很遠 並且有一些 spikes 這意味著雖然你的平均客戶有良好的體驗 但偶爾會有用戶必須等待幾乎兩倍的時間才能渲染頁面 理想情況下 你會希望讓所有這些值盡可能接近 為所有用戶創造更一致的體驗

例如 給定以下 duration set 其中 10 個客戶請求一個頁面 duration 在 100 milliseconds 和 1 秒之間

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

這將導致 mean 只有 190ms 而一個用戶有非常糟糕的 1 second response time 體驗 當只 tracking mean 時 更容易認為你的網站有很棒的 performance 而現實中偶爾用戶有可怕的體驗

上面的例子只有 10 個請求 想像如果你每天有一千個請求 那將意味著一百個用戶有可怕的體驗

Percentiles

為了給出值分佈更好的想法 我們使用 percentiles Percentiles 類似於 median - 一個數字表示數據集中一個點 其中一半集合在數字下方一半在上方 Percentiles 類似於 20th percentile 意味著數據集中 20% 的數字在該數字下方

給定以下 (sorted) set:

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

如果我們想知道 20th percentile 我們可以按以下方式計算: 集合中有 10 個值 想要的值在位置 1 (20.0 / 100 * 10 - 1) 因為我們的 arrays 從零開始 由於這個陣列包含偶數項目 我們必須計算 index (2) 和 index + 1 (3) 之間的 mean 這將導致 20th percentile 的值為 150

A very naive Ruby implementation 看起來像這樣:

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

# An array with an 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

# An array with an 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

這個 percentile function 看起來非常類似我們的 median 計算 事實上 median 等同於 50th percentile

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

AppSignal 使用上述統計數據為你的 Application 生成 performance metrics 我們不只依賴 mean/average 但計算 90th 和 95th percentiles 以顯示 outliers 給出你請求分佈更好的想法 在我們的 performance tour page 了解更多

Oddities

由於 percentiles 和 averages 計算方式 有時可能有 90th percentile dip below mean 例如 給定以下 dataset:

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

這將給我們 mean 182.73 和 90th percentile 只有 1

如果你的 metric collection system 只顯示 90th percentile 和 mean 你仍然能推斷出如果 90th percentile 掉到 average 以下 數據集中某處有一個 huge outlier

👋 如果你喜歡這篇文章 我們寫了更多關於 Ruby (on Rails) performance 的內容 查看我們的 Ruby performance monitoring checklist

You are almost at 100% of this post

這就是現在的全部! 在另一篇文章中 我們將談論我們如何使用 Quantiles 高效存儲和計算所有客戶請求的 percentiles 如果你有任何關於統計和 APMs, error tracking 或 performance monitoring 的問題或評論 在 Twitter @AppSignal 或通過 email 聯繫我們