#!/usr/bin/env bash # Copyright © 2023 OpenIM. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. : << EOF The API performance test script automatically executes wrk commands, collects data, analyzes it, and calls gnuplot to plot it Usage (to test API performance) : 1. Start the openim-api(port 10002) 2. Execute the test script: ./wrktest.sh The script will generate the data file.dat, each column meaning: concurrency QPS average response time success rate Usage (Compare the results of 2 tests) 1. The performance test:. / wrktest. Sh openim apiserver - http://127.0.0.1:10002/healthz 2. Execute the command:./wrktest.sh diff apiserver.dat http.dat > Note: Make sure you have wrk and gnuplot installed on your system EOF openim_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)" wrkdir="${openim_root}/_output/wrk" jobname="openim-api" duration="300s" threads=$((3 * $(grep -c processor /proc/cpuinfo))) source "${openim_root}/scripts/lib/color.sh" # Set wrk options openim::wrk::setup() { #concurrent="200 500 1000 3000 5000 10000 15000 20000 25000 50000 100000 200000 500000 1000000" concurrent="200 500 1000 3000 5000 10000 15000 20000 25000 50000" cmd="wrk -t${threads} -d${duration} -T30s --latency" } # Print usage openim::wrk::usage() { cat << EOF Usage: $0 [OPTION] [diff] URL Performance automation test script. URL HTTP request url, like: http://127.0.0.1:10002/healthz diff Compare two performance test results OPTIONS: -h Usage information -n Performance test task name, default: apiserver -d Directory used to store performance data and gnuplot graphic, default: _output/wrk Reprot bugs to <3293172751nss@gmail.com>. EOF } # Convert plot data to useable data function openim::wrk::convert_plot_data() { echo "$1" | awk -v datfile="${wrkdir}/${datfile}" ' { if ($0 ~ "Running") { common_time=$2 } if ($0 ~ "connections") { connections=$4 common_threads=$1 } if ($0 ~ "Latency ") { avg_latency=convertLatency($2) } if ($0 ~ "50%") { p50=convertLatency($2) } if ($0 ~ "75%") { p75=convertLatency($2) } if ($0 ~ "90%") { p90=convertLatency($2) } if ($0 ~ "99%") { p99=convertLatency($2) } if ($0 ~ "Requests/sec") { qps=$2 } if ($0 ~ "requests in") { allrequest=$1 } if ($0 ~ "Socket errors") { err=$4+$6+$8+$10 } } END { rate=sprintf("%.2f", (allrequest-err)*100/allrequest) print connections,qps,avg_latency,rate >> datfile } function convertLatency(s) { if (s ~ "us") { sub("us", "", s) return s/1000 } if (s ~ "ms") { sub("ms", "", s) return s } if (s ~ "s") { sub("s", "", s) return s * 1000 } }' } # Remove existing data file function openim::wrk::prepare() { rm -f "${wrkdir}"/"${datfile}" } # Plot according to gunplot data file function openim::wrk::plot() { gnuplot << EOF set terminal png enhanced #输出格式为png文件 set ylabel 'QPS' set xlabel 'Concurrent' set y2label 'Average Latency (ms)' set key top left vertical noreverse spacing 1.2 box set tics out nomirror set border 3 front set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 3 pointtype 2 set style line 2 linecolor rgb '#ff0000' linewidth 1 linetype 3 pointtype 2 set style data linespoints set grid #显示网格 set xtics nomirror rotate #by 90#只需要一个x轴 set mxtics 5 set mytics 5 #可以增加分刻度 set ytics nomirror set y2tics set autoscale y set autoscale y2 set output "${wrkdir}/${qpsttlb}" #指定数据文件名称 set title "QPS & TTLB\nRunning: ${duration}\nThreads: ${threads}" plot "${wrkdir}/${datfile}" using 2:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" axis x1y1 t "QPS","${wrkdir}/${datfile}" using 3:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#0000CD" axis x2y2 t "Avg Latency (ms)" unset y2tics unset y2label set ytics nomirror set yrange[0:100] set output "${wrkdir}/${successrate}" #指定数据文件名称 set title "Success Rate\nRunning: ${duration}\nThreads: ${threads}" plot "${wrkdir}/${datfile}" using 4:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#F62817" t "Success Rate" EOF } # Plot diff graphic function openim::wrk::plot_diff() { gnuplot << EOF set terminal png enhanced #输出格式为png文件 set xlabel 'Concurrent' set ylabel 'QPS' set y2label 'Average Latency (ms)' set key below left vertical noreverse spacing 1.2 box autotitle columnheader set tics out nomirror set border 3 front set style line 1 linecolor rgb '#00ff00' linewidth 2 linetype 3 pointtype 2 set style line 2 linecolor rgb '#ff0000' linewidth 1 linetype 3 pointtype 2 set style data linespoints #set border 3 lt 3 lw 2 #这会让你的坐标图的border更好看 set grid #显示网格 set xtics nomirror rotate #by 90#只需要一个x轴 set mxtics 5 set mytics 5 #可以增加分刻度 set ytics nomirror set y2tics #set pointsize 0.4 #点的像素大小 #set datafile separator '\t' #数据文件的字段用\t分开 set autoscale y set autoscale y2 #设置图像的大小 为标准大小的2倍 #set size 2.3,2 set output "${wrkdir}/${t1}_${t2}.qps.ttlb.diff.png" #指定数据文件名称 set title "QPS & TTLB\nRunning: ${duration}\nThreads: ${threads}" plot "/tmp/plot_diff.dat" using 2:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" axis x1y1 t "${t1} QPS","/tmp/plot_diff.dat" using 5:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE82EE" axis x1y1 t "${t2} QPS","/tmp/plot_diff.dat" using 3:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#0000CD" axis x2y2 t "${t1} Avg Latency (ms)", "/tmp/plot_diff.dat" using 6:xticlabels(1) w lp pt 5 ps 1 lc rgbcolor "#6495ED" axis x2y2 t "${t2} Avg Latency (ms)" unset y2tics unset y2label set ytics nomirror set yrange[0:100] set output "${wrkdir}/${t1}_${t2}.successrate.diff.png" #指定数据文件名称 set title "Success Rate\nRunning: ${duration}\nThreads: ${threads}" plot "/tmp/plot_diff.dat" using 4:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE0000" t "${t1} Success Rate","/tmp/plot_diff.dat" using 7:xticlabels(1) w lp pt 7 ps 1 lc rgbcolor "#EE82EE" t "${t2} Success Rate" EOF } # Start API performance testing openim::wrk::start_performance_test() { openim::wrk::prepare for c in ${concurrent} do wrkcmd="${cmd} -c ${c} $1" echo "Running wrk command: ${wrkcmd}" result=$(eval "${wrkcmd}") openim::wrk::convert_plot_data "${result}" done echo -e "\nNow plot according to ${COLOR_MAGENTA}${wrkdir}/${datfile}${COLOR_NORMAL}" openim::wrk::plot &> /dev/null echo -e "QPS graphic file is: ${COLOR_MAGENTA}${wrkdir}/${qpsttlb}${COLOR_NORMAL} Success rate graphic file is: ${COLOR_MAGENTA}${wrkdir}/${successrate}${COLOR_NORMAL}" } while getopts "hd:n:" opt;do case ${opt} in d) wrkdir=${OPTARG} ;; n) jobname=${OPTARG} ;; ?) openim::wrk::usage exit 0 ;; esac done shift $((OPTIND-1)) mkdir -p "${wrkdir}" case $1 in "diff") if [ "$#" -lt 3 ];then openim::wrk::usage exit 0 fi t1=$(basename $2|sed 's/.dat//g') # 对比图中红色线条名称 t2=$(basename $3|sed 's/.dat//g') # 对比图中粉色线条名称 join $2 $3 > /tmp/plot_diff.dat openim::wrk::plot_diff "$(basename "$2")" "$(basename "$3")" exit 0 ;; *) if [ "$#" -lt 1 ];then openim::wrk::usage exit 0 fi url="$1" qpsttlb="${jobname}_qps_ttlb.png" successrate="${jobname}_successrate.png" datfile="${jobname}.dat" openim::wrk::setup openim::wrk::start_performance_test "${url}" ;; esac