Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit 9cccb7c

Browse files
committed
Merge branch 'main' into analyze_port
2 parents e2cec2a + f5c7121 commit 9cccb7c

13 files changed

+315
-93
lines changed

.github/workflows/bench.yml

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,81 @@
11
name: "Run benchmark"
2-
32
on:
43
pull_request_target:
54
types: [assigned, opened, synchronize, reopened, edited]
65
push:
76
branches:
87
- main
9-
108
permissions:
119
contents: write
1210
pull-requests: write
1311
issues: write
14-
1512
jobs:
1613
build:
1714
runs-on: benchmarking-runner
1815
if: github.event.head_commit.message != 'Update performance results in README.md'
1916
env:
2017
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
strategy:
19+
matrix:
20+
service: [apollo_server, caliban, netflix_dgs, gqlgen, tailcall, async_graphql, hasura, graphql_jit]
2121
steps:
2222
- name: Checkout (GitHub)
2323
uses: actions/checkout@v4
2424
with:
2525
token: ${{ secrets.GITHUB_TOKEN }}
2626
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
27-
28-
- name: Build devcontainer and run benchmarks
27+
28+
- name: Build devcontainer and run setup and benchmark
2929
uses: devcontainers/[email protected]
3030
with:
3131
imageName: graphql-benchmarks
3232
push: never
3333
runCmd: |
34-
bash ./setup.sh
35-
bash ./run_benchmarks.sh
34+
bash ./graphql/${{ matrix.service }}/setup.sh
35+
bash run_benchmarks.sh ${{ matrix.service }}
36+
37+
- name: List benchmark files
38+
run: |
39+
ls -la bench*.txt || echo "No matching files found"
40+
41+
- name: Upload benchmark results
42+
uses: actions/upload-artifact@v3
43+
with:
44+
name: benchmark-results
45+
path: bench*.txt
46+
47+
48+
analyze:
49+
needs: benchmark
50+
runs-on: benchmarking-runner
51+
steps:
52+
- name: Checkout (GitHub)
53+
uses: actions/checkout@v4
54+
55+
- name: Download all benchmark results
56+
uses: actions/download-artifact@v3
57+
with:
58+
name: benchmark-results
59+
path: .
60+
61+
- name: List downloaded artifacts
62+
run: ls -la bench*.txt || echo "No matching files found"
63+
64+
- name: Analyze results
65+
run: |
66+
bash run_analyze_script.sh
3667
3768
- name: Print benchmark results
3869
run: cat ./results.md
39-
70+
4071
- name: Comment benchmark results on PR
4172
if: github.event_name == 'pull_request_target'
4273
uses: peter-evans/commit-comment@v3
4374
with:
4475
sha: ${{ github.event.pull_request.head.sha }}
4576
body-path: "results.md"
4677
reactions: eyes
47-
78+
4879
- name: Commit and push changes (on main branch)
4980
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
5081
uses: stefanzweifel/git-auto-commit-action@v5

README.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,32 @@ Get started with the benchmarks:
5151
| Query | Server | Requests/sec | Latency (ms) | Relative |
5252
|-------:|--------:|--------------:|--------------:|---------:|
5353
| 1 | `{ posts { id userId title user { id name email }}}` |
54-
|| [Tailcall] | `28,320.00` | `3.52` | `175.34x` |
55-
|| [async-graphql] | `1,784.61` | `57.51` | `11.05x` |
56-
|| [Caliban] | `1,523.52` | `65.29` | `9.43x` |
57-
|| [GraphQL JIT] | `1,311.50` | `75.93` | `8.12x` |
58-
|| [Gqlgen] | `744.41` | `133.27` | `4.61x` |
59-
|| [Netflix DGS] | `354.53` | `192.91` | `2.20x` |
60-
|| [Apollo GraphQL] | `264.73` | `370.46` | `1.64x` |
61-
|| [Hasura] | `161.51` | `496.54` | `1.00x` |
54+
|| [Tailcall] | `29,496.60` | `3.38` | `196.74x` |
55+
|| [async-graphql] | `1,805.45` | `55.70` | `12.04x` |
56+
|| [Caliban] | `1,547.91` | `64.33` | `10.32x` |
57+
|| [GraphQL JIT] | `1,335.26` | `74.60` | `8.91x` |
58+
|| [Gqlgen] | `772.80` | `128.41` | `5.15x` |
59+
|| [Netflix DGS] | `358.06` | `177.42` | `2.39x` |
60+
|| [Apollo GraphQL] | `268.25` | `366.16` | `1.79x` |
61+
|| [Hasura] | `149.93` | `549.07` | `1.00x` |
6262
| 2 | `{ posts { title }}` |
63-
|| [Tailcall] | `58,223.00` | `1.71` | `68.82x` |
64-
|| [Caliban] | `9,102.02` | `11.33` | `10.76x` |
65-
|| [async-graphql] | `9,042.00` | `11.20` | `10.69x` |
66-
|| [Gqlgen] | `2,136.74` | `48.34` | `2.53x` |
67-
|| [Apollo GraphQL] | `1,742.58` | `57.30` | `2.06x` |
68-
|| [Netflix DGS] | `1,584.25` | `69.49` | `1.87x` |
69-
|| [GraphQL JIT] | `1,337.30` | `74.68` | `1.58x` |
70-
|| [Hasura] | `845.98` | `117.95` | `1.00x` |
63+
|| [Tailcall] | `58,939.60` | `1.69` | `67.77x` |
64+
|| [Caliban] | `9,238.76` | `11.16` | `10.62x` |
65+
|| [async-graphql] | `9,138.76` | `11.34` | `10.51x` |
66+
|| [Gqlgen] | `2,136.19` | `48.48` | `2.46x` |
67+
|| [Apollo GraphQL] | `1,775.87` | `56.26` | `2.04x` |
68+
|| [Netflix DGS] | `1,593.80` | `69.82` | `1.83x` |
69+
|| [GraphQL JIT] | `1,399.68` | `71.35` | `1.61x` |
70+
|| [Hasura] | `869.69` | `114.81` | `1.00x` |
7171
| 3 | `{ greet }` |
72-
|| [Caliban] | `66,940.20` | `1.09` | `26.59x` |
73-
|| [Tailcall] | `59,316.40` | `1.70` | `23.56x` |
74-
|| [async-graphql] | `47,630.90` | `2.14` | `18.92x` |
75-
|| [Gqlgen] | `46,908.30` | `5.23` | `18.63x` |
76-
|| [Netflix DGS] | `8,151.83` | `15.19` | `3.24x` |
77-
|| [Apollo GraphQL] | `7,931.63` | `12.75` | `3.15x` |
78-
|| [GraphQL JIT] | `5,147.67` | `19.40` | `2.04x` |
79-
|| [Hasura] | `2,517.36` | `39.64` | `1.00x` |
72+
|| [Caliban] | `67,637.00` | `1.07` | `25.83x` |
73+
|| [Tailcall] | `59,557.80` | `1.69` | `22.75x` |
74+
|| [Gqlgen] | `47,525.20` | `5.21` | `18.15x` |
75+
|| [async-graphql] | `47,150.60` | `2.21` | `18.01x` |
76+
|| [Netflix DGS] | `8,261.44` | `15.02` | `3.16x` |
77+
|| [Apollo GraphQL] | `8,186.12` | `12.54` | `3.13x` |
78+
|| [GraphQL JIT] | `5,273.45` | `18.93` | `2.01x` |
79+
|| [Hasura] | `2,618.18` | `38.13` | `1.00x` |
8080

8181
<!-- PERFORMANCE_RESULTS_END -->
8282

analyze.sh

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#!/bin/bash
2+
3+
# Install gnuplot
4+
sudo apt-get update && sudo apt-get install -y gnuplot
5+
6+
function extractMetric() {
7+
local file="$1"
8+
local metric="$2"
9+
grep "$metric" "$file" | awk '{print $2}' | sed 's/ms//'
10+
}
11+
12+
function average() {
13+
echo "$@" | awk '{for(i=1;i<=NF;i++) s+=$i; print s/NF}'
14+
}
15+
16+
declare -A formattedServerNames
17+
formattedServerNames=(
18+
["tailcall"]="Tailcall"
19+
["gqlgen"]="Gqlgen"
20+
["apollo"]="Apollo GraphQL"
21+
["netflixdgs"]="Netflix DGS"
22+
["caliban"]="Caliban"
23+
["async_graphql"]="async-graphql"
24+
["hasura"]="Hasura"
25+
["graphql_jit"]="GraphQL JIT"
26+
)
27+
28+
servers=("apollo" "caliban" "netflixdgs" "gqlgen" "tailcall" "async_graphql" "hasura" "graphql_jit")
29+
resultFiles=("$@")
30+
declare -A avgReqSecs
31+
declare -A avgLatencies
32+
33+
# Extract metrics and calculate averages
34+
for idx in "${!servers[@]}"; do
35+
startIdx=$((idx * 3))
36+
reqSecVals=()
37+
latencyVals=()
38+
for j in 0 1 2; do
39+
fileIdx=$((startIdx + j))
40+
reqSecVals+=($(extractMetric "${resultFiles[$fileIdx]}" "Requests/sec"))
41+
latencyVals+=($(extractMetric "${resultFiles[$fileIdx]}" "Latency"))
42+
done
43+
avgReqSecs[${servers[$idx]}]=$(average "${reqSecVals[@]}")
44+
avgLatencies[${servers[$idx]}]=$(average "${latencyVals[@]}")
45+
done
46+
47+
# Generating data files for gnuplot
48+
reqSecData="/tmp/reqSec.dat"
49+
latencyData="/tmp/latency.dat"
50+
51+
echo "Server Value" >"$reqSecData"
52+
for server in "${servers[@]}"; do
53+
echo "$server ${avgReqSecs[$server]}" >>"$reqSecData"
54+
done
55+
56+
echo "Server Value" >"$latencyData"
57+
for server in "${servers[@]}"; do
58+
echo "$server ${avgLatencies[$server]}" >>"$latencyData"
59+
done
60+
61+
whichBench=1
62+
if [[ $1 == bench2* ]]; then
63+
whichBench=2
64+
elif [[ $1 == bench3* ]]; then
65+
whichBench=3
66+
fi
67+
68+
reqSecHistogramFile="req_sec_histogram${whichBench}.png"
69+
latencyHistogramFile="latency_histogram${whichBench}.png"
70+
71+
# Plotting using gnuplot
72+
gnuplot <<-EOF
73+
set term pngcairo size 1280,720 enhanced font "Courier,12"
74+
set output "$reqSecHistogramFile"
75+
set style data histograms
76+
set style histogram cluster gap 1
77+
set style fill solid border -1
78+
set xtics rotate by -45
79+
set boxwidth 0.9
80+
set title "Requests/Sec"
81+
stats "$reqSecData" using 2 nooutput
82+
set yrange [0:STATS_max*1.2]
83+
set key outside right top
84+
plot "$reqSecData" using 2:xtic(1) title "Req/Sec"
85+
86+
set output "$latencyHistogramFile"
87+
set title "Latency (in ms)"
88+
stats "$latencyData" using 2 nooutput
89+
set yrange [0:STATS_max*1.2]
90+
plot "$latencyData" using 2:xtic(1) title "Latency"
91+
EOF
92+
93+
# Move PNGs to assets
94+
mkdir -p assets
95+
mv $reqSecHistogramFile assets/
96+
mv $latencyHistogramFile assets/
97+
98+
# Declare an associative array for server RPS
99+
declare -A serverRPS
100+
101+
# Populate the serverRPS array
102+
for server in "${servers[@]}"; do
103+
serverRPS[$server]=${avgReqSecs[$server]}
104+
done
105+
106+
# Get the servers sorted by RPS in descending order
107+
IFS=$'\n' sortedServers=($(for server in "${!serverRPS[@]}"; do echo "$server ${serverRPS[$server]}"; done | sort -rn -k2 | cut -d' ' -f1))
108+
109+
echo "Sorted servers: ${sortedServers[@]}"
110+
lastServer="${sortedServers[-1]}"
111+
lastServerReqSecs=${avgReqSecs[$lastServer]}
112+
113+
# Start building the resultsTable
114+
if [[ $whichBench == 1 ]]; then
115+
resultsTable="<!-- PERFORMANCE_RESULTS_START -->\n\n| Query | Server | Requests/sec | Latency (ms) | Relative |\n|-------:|--------:|--------------:|--------------:|---------:|\n| $whichBench | \`{ posts { id userId title user { id name email }}}\` |"
116+
elif [[ $whichBench == 2 ]]; then
117+
resultsTable="| $whichBench | \`{ posts { title }}\` |"
118+
elif [[ $whichBench == 3 ]]; then
119+
resultsTable="| $whichBench | \`{ greet }\` |"
120+
fi
121+
122+
# Build the resultsTable with sorted servers and formatted numbers
123+
for server in "${sortedServers[@]}"; do
124+
formattedReqSecs=$(printf "%.2f" ${avgReqSecs[$server]} | perl -pe 's/(?<=\d)(?=(\d{3})+(\.\d*)?$)/,/g')
125+
formattedLatencies=$(printf "%.2f" ${avgLatencies[$server]} | perl -pe 's/(?<=\d)(?=(\d{3})+(\.\d*)?$)/,/g')
126+
# Calculate the relative performance
127+
relativePerformance=$(echo "${avgReqSecs[$server]} $lastServerReqSecs" | awk '{printf "%.2f", $1 / $2}')
128+
129+
resultsTable+="\n|| [${formattedServerNames[$server]}] | \`${formattedReqSecs}\` | \`${formattedLatencies}\` | \`${relativePerformance}x\` |"
130+
done
131+
132+
if [[ $whichBench == 3 ]]; then
133+
resultsTable+="\n\n<!-- PERFORMANCE_RESULTS_END -->"
134+
fi
135+
136+
echo "resultsTable: $resultsTable"
137+
138+
# Print the results table in a new file
139+
resultsFile="results.md"
140+
echo -e $resultsTable >> $resultsFile
141+
142+
143+
if [[ $whichBench == 3 ]]; then
144+
finalResults=$(printf '%s\n' "$(cat $resultsFile)" | sed 's/$/\\n/'| tr -d '\n')
145+
# Remove the last newline character
146+
finalResults=${finalResults::-2}
147+
148+
# Print the results as a table in the terminal
149+
echo -e $finalResults | sed "s/<!-- PERFORMANCE_RESULTS_START-->//;s/<!-- PERFORMANCE_RESULTS_END-->//"
150+
# Check if the markers are present
151+
if grep -q "PERFORMANCE_RESULTS_START" README.md; then
152+
# Replace the old results with the new results
153+
sed -i "/PERFORMANCE_RESULTS_START/,/PERFORMANCE_RESULTS_END/c\\$finalResults" README.md
154+
else
155+
# Append the results at the end of the README.md file
156+
echo -e "\n$finalResults" >> README.md
157+
fi
158+
fi
159+
160+
# Move the generated images to the assets folder
161+
mv $reqSecHistogramFile assets/
162+
mv $latencyHistogramFile assets/
163+
164+
# Delete the result TXT files
165+
for file in "${resultFiles[@]}"; do
166+
rm "$file"
167+
done

assets/latency_histogram1.png

587 Bytes
Loading

assets/latency_histogram2.png

-594 Bytes
Loading

assets/latency_histogram3.png

-43 Bytes
Loading

assets/req_sec_histogram1.png

684 Bytes
Loading

assets/req_sec_histogram2.png

412 Bytes
Loading

assets/req_sec_histogram3.png

-50 Bytes
Loading

graphql/apollo_server/package-lock.json

Lines changed: 6 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)