0%

使用 awk 统计 p99

最近在重构公司内的一个重要服务,目前已经把主要流程写完了,由于新写的服务对底层的存储组件进行了变更,所以要对性能进行一个对比。

老服务的监控不是太完善,接口平均时延、p99 之类的都没有上报到 Prometheus 里,只在日志文件中进行了每次请求响应时间的统计,所以我写了一个 Python 脚本遍历所有日志,从中抽取出我需要的数值,然后将这些时间进行加和再除以数量就可以得到平均时间了。但是 p90、p95、p99 这些还需要我再去编写额外的代码逻辑进行统计。

因为太懒了,不想去写那些统计逻辑,于是从网上搜了下有没有现成的脚本,找到了一个使用 awk 统计时延的脚本,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#! /usr/bin/awk -f  
{variance=0;sumCount+=$1;sumCost+=($2*$1);count[NR]=$1;cost[NR]=$2}
END {
staticTotal[0]=50;
staticTotal[1]=66;
staticTotal[2]=80;
staticTotal[3]=85;
staticTotal[4]=90;
staticTotal[5]=95;
staticTotal[6]=98;
staticTotal[7]=99;
staticTotal[8]=99.9;
staticFlag[0]=1;
staticFlag[1]=1;
staticFlag[2]=1;
staticFlag[3]=1;
staticFlag[4]=1;
staticFlag[5]=1;
staticFlag[6]=1;
staticFlag[7]=1;
staticFlag[8]=1;
printf "%3s %10s %15s %15s\n", "static", "costt", "count", "diffPre";
averageCost = sumCost/sumCount;
for(i=1; i <=length(count); i++) {
diff = (cost[i] - averageCost);
variance += (diff*diff*count[i]/(sumCount-1));
#printf("diff %s, variance %s, count[%s]: %s, cost[%s]: %s \n", diff, variance, i, count[i], i, cost[i]);
countTotal += count[i];
for (j=0; j <length(staticTotal); j++) {
if (countTotal >= sumCount*staticTotal[j]/100) if (staticFlag[j]==1) {
staticFlag[j]=sprintf("P%-3s %10s %15s %15s", staticTotal[j],cost[i],countTotal, countTotal - countTotalPre); countTotalPre = countTotal;
}
}
};

for( i=0;i<length(staticFlag);i++) print staticFlag[i];
printf "count total: %s\n", sumCount, countTotal;
printf "average cost: %s \n", averageCost;
printf "variance cost: %s \n", variance;
}

用法也很简单,准备好我们每次请求响应时间的数据,一行一条,如:

1
2
3
4
5
6
7
8
9
10
11
1.803322
12.561867
3.819391
0.468846
23.792512
0.362949
0.347554
2.739202
12.407241
39.385484
...

假如我们的数据文件叫做 time.log,将上边的脚本保存为 cal.awk,用一下命令就可以得出时延的统计信息了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat time.log | sort -n | uniq -c | awk -f cal.awk
static costt count diffPre
P50 3.154644 50000 50000
P66 5.481086 66000 16000
P80 9.649493 80000 14000
P85 12.548806 85000 5000
P90 17.208233 90000 5000
P95 26.653718 95000 5000
P98 42.952164 98000 3000
P99 59.790145 99000 1000
P99.9 102.811803 99900 900
count total: 100000
average cost: 7.03982
variance cost: 128.59

这条命令组合了 sort 对数据进行排序、uniq 对数据进行去重+次数统计,最后调用我们的 awk 脚本实现统计。

可以看到统计的种类很全,p50、p90、p99 都有,还有平均值和方差,非常方便。