Skip to content

Commit

Permalink
Merge branch 'main' into analyze_port
Browse files Browse the repository at this point in the history
  • Loading branch information
daveads committed Jul 23, 2024
2 parents e2cec2a + f5c7121 commit 9cccb7c
Show file tree
Hide file tree
Showing 13 changed files with 315 additions and 93 deletions.
49 changes: 40 additions & 9 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -1,50 +1,81 @@
name: "Run benchmark"

on:
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
push:
branches:
- main

permissions:
contents: write
pull-requests: write
issues: write

jobs:
build:
runs-on: benchmarking-runner
if: github.event.head_commit.message != 'Update performance results in README.md'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix:
service: [apollo_server, caliban, netflix_dgs, gqlgen, tailcall, async_graphql, hasura, graphql_jit]
steps:
- name: Checkout (GitHub)
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}

- name: Build devcontainer and run benchmarks
- name: Build devcontainer and run setup and benchmark
uses: devcontainers/[email protected]
with:
imageName: graphql-benchmarks
push: never
runCmd: |
bash ./setup.sh
bash ./run_benchmarks.sh
bash ./graphql/${{ matrix.service }}/setup.sh
bash run_benchmarks.sh ${{ matrix.service }}
- name: List benchmark files
run: |
ls -la bench*.txt || echo "No matching files found"
- name: Upload benchmark results
uses: actions/upload-artifact@v3
with:
name: benchmark-results
path: bench*.txt


analyze:
needs: benchmark
runs-on: benchmarking-runner
steps:
- name: Checkout (GitHub)
uses: actions/checkout@v4

- name: Download all benchmark results
uses: actions/download-artifact@v3
with:
name: benchmark-results
path: .

- name: List downloaded artifacts
run: ls -la bench*.txt || echo "No matching files found"

- name: Analyze results
run: |
bash run_analyze_script.sh
- name: Print benchmark results
run: cat ./results.md

- name: Comment benchmark results on PR
if: github.event_name == 'pull_request_target'
uses: peter-evans/commit-comment@v3
with:
sha: ${{ github.event.pull_request.head.sha }}
body-path: "results.md"
reactions: eyes

- name: Commit and push changes (on main branch)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: stefanzweifel/git-auto-commit-action@v5
Expand Down
48 changes: 24 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,32 @@ Get started with the benchmarks:
| Query | Server | Requests/sec | Latency (ms) | Relative |
|-------:|--------:|--------------:|--------------:|---------:|
| 1 | `{ posts { id userId title user { id name email }}}` |
|| [Tailcall] | `28,320.00` | `3.52` | `175.34x` |
|| [async-graphql] | `1,784.61` | `57.51` | `11.05x` |
|| [Caliban] | `1,523.52` | `65.29` | `9.43x` |
|| [GraphQL JIT] | `1,311.50` | `75.93` | `8.12x` |
|| [Gqlgen] | `744.41` | `133.27` | `4.61x` |
|| [Netflix DGS] | `354.53` | `192.91` | `2.20x` |
|| [Apollo GraphQL] | `264.73` | `370.46` | `1.64x` |
|| [Hasura] | `161.51` | `496.54` | `1.00x` |
|| [Tailcall] | `29,496.60` | `3.38` | `196.74x` |
|| [async-graphql] | `1,805.45` | `55.70` | `12.04x` |
|| [Caliban] | `1,547.91` | `64.33` | `10.32x` |
|| [GraphQL JIT] | `1,335.26` | `74.60` | `8.91x` |
|| [Gqlgen] | `772.80` | `128.41` | `5.15x` |
|| [Netflix DGS] | `358.06` | `177.42` | `2.39x` |
|| [Apollo GraphQL] | `268.25` | `366.16` | `1.79x` |
|| [Hasura] | `149.93` | `549.07` | `1.00x` |
| 2 | `{ posts { title }}` |
|| [Tailcall] | `58,223.00` | `1.71` | `68.82x` |
|| [Caliban] | `9,102.02` | `11.33` | `10.76x` |
|| [async-graphql] | `9,042.00` | `11.20` | `10.69x` |
|| [Gqlgen] | `2,136.74` | `48.34` | `2.53x` |
|| [Apollo GraphQL] | `1,742.58` | `57.30` | `2.06x` |
|| [Netflix DGS] | `1,584.25` | `69.49` | `1.87x` |
|| [GraphQL JIT] | `1,337.30` | `74.68` | `1.58x` |
|| [Hasura] | `845.98` | `117.95` | `1.00x` |
|| [Tailcall] | `58,939.60` | `1.69` | `67.77x` |
|| [Caliban] | `9,238.76` | `11.16` | `10.62x` |
|| [async-graphql] | `9,138.76` | `11.34` | `10.51x` |
|| [Gqlgen] | `2,136.19` | `48.48` | `2.46x` |
|| [Apollo GraphQL] | `1,775.87` | `56.26` | `2.04x` |
|| [Netflix DGS] | `1,593.80` | `69.82` | `1.83x` |
|| [GraphQL JIT] | `1,399.68` | `71.35` | `1.61x` |
|| [Hasura] | `869.69` | `114.81` | `1.00x` |
| 3 | `{ greet }` |
|| [Caliban] | `66,940.20` | `1.09` | `26.59x` |
|| [Tailcall] | `59,316.40` | `1.70` | `23.56x` |
|| [async-graphql] | `47,630.90` | `2.14` | `18.92x` |
|| [Gqlgen] | `46,908.30` | `5.23` | `18.63x` |
|| [Netflix DGS] | `8,151.83` | `15.19` | `3.24x` |
|| [Apollo GraphQL] | `7,931.63` | `12.75` | `3.15x` |
|| [GraphQL JIT] | `5,147.67` | `19.40` | `2.04x` |
|| [Hasura] | `2,517.36` | `39.64` | `1.00x` |
|| [Caliban] | `67,637.00` | `1.07` | `25.83x` |
|| [Tailcall] | `59,557.80` | `1.69` | `22.75x` |
|| [Gqlgen] | `47,525.20` | `5.21` | `18.15x` |
|| [async-graphql] | `47,150.60` | `2.21` | `18.01x` |
|| [Netflix DGS] | `8,261.44` | `15.02` | `3.16x` |
|| [Apollo GraphQL] | `8,186.12` | `12.54` | `3.13x` |
|| [GraphQL JIT] | `5,273.45` | `18.93` | `2.01x` |
|| [Hasura] | `2,618.18` | `38.13` | `1.00x` |

<!-- PERFORMANCE_RESULTS_END -->

Expand Down
167 changes: 167 additions & 0 deletions analyze.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#!/bin/bash

# Install gnuplot
sudo apt-get update && sudo apt-get install -y gnuplot

function extractMetric() {
local file="$1"
local metric="$2"
grep "$metric" "$file" | awk '{print $2}' | sed 's/ms//'
}

function average() {
echo "$@" | awk '{for(i=1;i<=NF;i++) s+=$i; print s/NF}'
}

declare -A formattedServerNames
formattedServerNames=(
["tailcall"]="Tailcall"
["gqlgen"]="Gqlgen"
["apollo"]="Apollo GraphQL"
["netflixdgs"]="Netflix DGS"
["caliban"]="Caliban"
["async_graphql"]="async-graphql"
["hasura"]="Hasura"
["graphql_jit"]="GraphQL JIT"
)

servers=("apollo" "caliban" "netflixdgs" "gqlgen" "tailcall" "async_graphql" "hasura" "graphql_jit")
resultFiles=("$@")
declare -A avgReqSecs
declare -A avgLatencies

# Extract metrics and calculate averages
for idx in "${!servers[@]}"; do
startIdx=$((idx * 3))
reqSecVals=()
latencyVals=()
for j in 0 1 2; do
fileIdx=$((startIdx + j))
reqSecVals+=($(extractMetric "${resultFiles[$fileIdx]}" "Requests/sec"))
latencyVals+=($(extractMetric "${resultFiles[$fileIdx]}" "Latency"))
done
avgReqSecs[${servers[$idx]}]=$(average "${reqSecVals[@]}")
avgLatencies[${servers[$idx]}]=$(average "${latencyVals[@]}")
done

# Generating data files for gnuplot
reqSecData="/tmp/reqSec.dat"
latencyData="/tmp/latency.dat"

echo "Server Value" >"$reqSecData"
for server in "${servers[@]}"; do
echo "$server ${avgReqSecs[$server]}" >>"$reqSecData"
done

echo "Server Value" >"$latencyData"
for server in "${servers[@]}"; do
echo "$server ${avgLatencies[$server]}" >>"$latencyData"
done

whichBench=1
if [[ $1 == bench2* ]]; then
whichBench=2
elif [[ $1 == bench3* ]]; then
whichBench=3
fi

reqSecHistogramFile="req_sec_histogram${whichBench}.png"
latencyHistogramFile="latency_histogram${whichBench}.png"

# Plotting using gnuplot
gnuplot <<-EOF
set term pngcairo size 1280,720 enhanced font "Courier,12"
set output "$reqSecHistogramFile"
set style data histograms
set style histogram cluster gap 1
set style fill solid border -1
set xtics rotate by -45
set boxwidth 0.9
set title "Requests/Sec"
stats "$reqSecData" using 2 nooutput
set yrange [0:STATS_max*1.2]
set key outside right top
plot "$reqSecData" using 2:xtic(1) title "Req/Sec"
set output "$latencyHistogramFile"
set title "Latency (in ms)"
stats "$latencyData" using 2 nooutput
set yrange [0:STATS_max*1.2]
plot "$latencyData" using 2:xtic(1) title "Latency"
EOF

# Move PNGs to assets
mkdir -p assets
mv $reqSecHistogramFile assets/
mv $latencyHistogramFile assets/

# Declare an associative array for server RPS
declare -A serverRPS

# Populate the serverRPS array
for server in "${servers[@]}"; do
serverRPS[$server]=${avgReqSecs[$server]}
done

# Get the servers sorted by RPS in descending order
IFS=$'\n' sortedServers=($(for server in "${!serverRPS[@]}"; do echo "$server ${serverRPS[$server]}"; done | sort -rn -k2 | cut -d' ' -f1))

echo "Sorted servers: ${sortedServers[@]}"
lastServer="${sortedServers[-1]}"
lastServerReqSecs=${avgReqSecs[$lastServer]}

# Start building the resultsTable
if [[ $whichBench == 1 ]]; then
resultsTable="<!-- PERFORMANCE_RESULTS_START -->\n\n| Query | Server | Requests/sec | Latency (ms) | Relative |\n|-------:|--------:|--------------:|--------------:|---------:|\n| $whichBench | \`{ posts { id userId title user { id name email }}}\` |"
elif [[ $whichBench == 2 ]]; then
resultsTable="| $whichBench | \`{ posts { title }}\` |"
elif [[ $whichBench == 3 ]]; then
resultsTable="| $whichBench | \`{ greet }\` |"
fi

# Build the resultsTable with sorted servers and formatted numbers
for server in "${sortedServers[@]}"; do
formattedReqSecs=$(printf "%.2f" ${avgReqSecs[$server]} | perl -pe 's/(?<=\d)(?=(\d{3})+(\.\d*)?$)/,/g')
formattedLatencies=$(printf "%.2f" ${avgLatencies[$server]} | perl -pe 's/(?<=\d)(?=(\d{3})+(\.\d*)?$)/,/g')
# Calculate the relative performance
relativePerformance=$(echo "${avgReqSecs[$server]} $lastServerReqSecs" | awk '{printf "%.2f", $1 / $2}')

resultsTable+="\n|| [${formattedServerNames[$server]}] | \`${formattedReqSecs}\` | \`${formattedLatencies}\` | \`${relativePerformance}x\` |"
done

if [[ $whichBench == 3 ]]; then
resultsTable+="\n\n<!-- PERFORMANCE_RESULTS_END -->"
fi

echo "resultsTable: $resultsTable"

# Print the results table in a new file
resultsFile="results.md"
echo -e $resultsTable >> $resultsFile


if [[ $whichBench == 3 ]]; then
finalResults=$(printf '%s\n' "$(cat $resultsFile)" | sed 's/$/\\n/'| tr -d '\n')
# Remove the last newline character
finalResults=${finalResults::-2}

# Print the results as a table in the terminal
echo -e $finalResults | sed "s/<!-- PERFORMANCE_RESULTS_START-->//;s/<!-- PERFORMANCE_RESULTS_END-->//"
# Check if the markers are present
if grep -q "PERFORMANCE_RESULTS_START" README.md; then
# Replace the old results with the new results
sed -i "/PERFORMANCE_RESULTS_START/,/PERFORMANCE_RESULTS_END/c\\$finalResults" README.md
else
# Append the results at the end of the README.md file
echo -e "\n$finalResults" >> README.md
fi
fi

# Move the generated images to the assets folder
mv $reqSecHistogramFile assets/
mv $latencyHistogramFile assets/

# Delete the result TXT files
for file in "${resultFiles[@]}"; do
rm "$file"
done
Binary file modified assets/latency_histogram1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/latency_histogram2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/latency_histogram3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/req_sec_histogram1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/req_sec_histogram2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/req_sec_histogram3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 6 additions & 18 deletions graphql/apollo_server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

1 comment on commit 9cccb7c

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Query Server Requests/sec Latency (ms) Relative
1 { posts { id userId title user { id name email }}}
[Tailcall] 29,936.40 3.33 211.26x
[async-graphql] 2,016.18 49.98 14.23x
[Caliban] 1,712.35 58.36 12.08x
[GraphQL JIT] 1,364.91 72.93 9.63x
[Gqlgen] 809.03 122.67 5.71x
[Netflix DGS] 375.06 163.39 2.65x
[Apollo GraphQL] 268.25 366.50 1.89x
[Hasura] 141.71 506.80 1.00x
2 { posts { title }}
[Tailcall] 59,464.00 1.67 68.27x
[async-graphql] 9,741.44 10.38 11.18x
[Caliban] 9,572.28 10.81 10.99x
[Gqlgen] 2,227.65 46.40 2.56x
[Apollo GraphQL] 1,762.85 56.66 2.02x
[Netflix DGS] 1,619.04 69.12 1.86x
[GraphQL JIT] 1,405.45 71.06 1.61x
[Hasura] 871.07 114.54 1.00x
3 { greet }
[Caliban] 67,270.10 1.07 25.15x
[Tailcall] 60,461.50 1.66 22.61x
[async-graphql] 48,630.80 2.09 18.18x
[Gqlgen] 47,768.60 5.05 17.86x
[Netflix DGS] 8,345.89 14.39 3.12x
[Apollo GraphQL] 8,052.06 12.73 3.01x
[GraphQL JIT] 5,307.81 18.82 1.98x
[Hasura] 2,674.53 37.39 1.00x

Please sign in to comment.