Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/mozilla/neqo into recvmmsg
Browse files Browse the repository at this point in the history
  • Loading branch information
mxinden committed Apr 3, 2024
2 parents cfcea21 + 0751429 commit e2e54fa
Show file tree
Hide file tree
Showing 72 changed files with 1,574 additions and 843 deletions.
33 changes: 33 additions & 0 deletions .github/actions/nss/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,68 @@ inputs:
runs:
using: composite
steps:
- name: Check system NSS version
shell: bash
run: |
if ! command -v pkg-config &> /dev/null; then
echo "BUILD_NSS=1" >> "$GITHUB_ENV"
exit 0
fi
if ! pkg-config --exists nss; then
echo "BUILD_NSS=1" >> "$GITHUB_ENV"
exit 0
fi
NSS_VERSION="$(pkg-config --modversion nss)"
if [ "$?" -ne 0 ]; then
echo "BUILD_NSS=1" >> "$GITHUB_ENV"
exit 0
fi
NSS_MAJOR=$(echo "$NSS_VERSION" | cut -d. -f1)
NSS_MINOR=$(echo "$NSS_VERSION" | cut -d. -f2)
REQ_NSS_MAJOR=$(cut -d. -f1 < neqo-crypto/min_version.txt)
REQ_NSS_MINOR=$(cut -d. -f2 < neqo-crypto/min_version.txt)
if [[ "$NSS_MAJOR" -lt "$REQ_NSS_MAJOR" || "$NSS_MAJOR" -eq "$REQ_NSS_MAJOR" && "$NSS_MINOR" -lt "$REQ_NSS_MINOR" ]]; then
echo "System NSS is too old: $NSS_VERSION"
echo "BUILD_NSS=1" >> "$GITHUB_ENV"
exit 0
fi
echo "System NSS is suitable: $NSS_VERSION"
echo "BUILD_NSS=0" >> "$GITHUB_ENV"
# Ideally, we'd use this. But things are sufficiently flaky that we're better off
# trying both hg and git. Leaving this here in case we want to re-try in the future.
#
# - name: Checkout NSPR
# if: env.BUILD_NSS == '1'
# uses: actions/checkout@v4
# with:
# repository: "nss-dev/nspr"
# path: ${{ github.workspace }}/nspr

# - name: Checkout NSS
# if: env.BUILD_NSS == '1'
# uses: actions/checkout@v4
# with:
# repository: "nss-dev/nss"
# path: ${{ github.workspace }}/nss

- name: Checkout NSPR
shell: bash
if: env.BUILD_NSS == '1'
run: |
hg clone https://hg.mozilla.org/projects/nspr "${{ github.workspace }}/nspr" || \
git clone --depth=1 https://github.com/nss-dev/nspr "${{ github.workspace }}/nspr"
- name: Checkout NSS
shell: bash
if: env.BUILD_NSS == '1'
run: |
hg clone https://hg.mozilla.org/projects/nss "${{ github.workspace }}/nss" || \
git clone --depth=1 https://github.com/nss-dev/nss "${{ github.workspace }}/nss"
- name: Build
shell: bash
if: env.BUILD_NSS == '1'
run: |
if [ "${{ inputs.type }}" != "Debug" ]; then
# We want to do an optimized build for accurate CPU profiling, but
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/quic-interop-runner/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ runs:
run: |
echo '[**QUIC Interop Runner**](https://github.com/quic-interop/quic-interop-runner)' >> comment
echo '' >> comment
# Ignore all, but table, which starts with "|:--".
cat quic-interop-runner/summary | awk '/^\|:--/{flag=1} flag' >> comment
# Ignore all, but table, which starts with "|".
grep -E '^\|' quic-interop-runner/summary >> comment
echo '' >> comment
shell: bash

Expand Down
2 changes: 1 addition & 1 deletion .github/actions/rust/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ runs:

- name: Install Rust tools
shell: bash
run: cargo +${{ inputs.version }} binstall --no-confirm cargo-llvm-cov cargo-nextest flamegraph cargo-hack cargo-mutants
run: cargo +${{ inputs.version }} binstall --no-confirm cargo-llvm-cov cargo-nextest flamegraph cargo-hack cargo-mutants hyperfine

# sccache slows CI down, so we leave it disabled.
# Leaving the steps below commented out, so we can re-evaluate enabling it later.
Expand Down
171 changes: 125 additions & 46 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ name: Bench
on:
workflow_call:
workflow_dispatch:
schedule:
# Run at 1 AM each day, so there is a `main`-branch baseline in the cache.
- cron: '0 1 * * *'
env:
CARGO_PROFILE_BENCH_BUILD_OVERRIDE_DEBUG: true
CARGO_PROFILE_RELEASE_DEBUG: true
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
TOOLCHAIN: nightly
RUSTFLAGS: -C link-arg=-fuse-ld=lld -C link-arg=-Wl,--no-rosegment, -C force-frame-pointers=yes
PERF_CMD: record -o perf.data -F997 --call-graph fp -g
PERF_OPT: record -F997 --call-graph fp -g

jobs:
bench:
Expand All @@ -20,9 +23,17 @@ jobs:
shell: bash

steps:
- name: Checkout
- name: Checkout neqo
uses: actions/checkout@v4

- name: Checkout msquic
uses: actions/checkout@v4
with:
repository: microsoft/msquic
ref: main
path: msquic
submodules: true

- name: Set PATH
run: echo "/home/bench/.cargo/bin" >> "${GITHUB_PATH}"

Expand All @@ -35,10 +46,17 @@ jobs:
- name: Fetch and build NSS and NSPR
uses: ./.github/actions/nss

- name: Build
- name: Build neqo
run: |
cargo "+$TOOLCHAIN" bench --features bench --no-run
cargo "+$TOOLCHAIN" build --release --bin neqo-client --bin neqo-server
cargo "+$TOOLCHAIN" build --release
- name: Build msquic
run: |
mkdir -p msquic/build
cd msquic/build
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DQUIC_BUILD_TOOLS=1 -DQUIC_BUILD_PERF=1 ..
cmake --build .
- name: Download cached main-branch results
id: criterion-cache
Expand All @@ -52,70 +70,125 @@ jobs:
- name: Prepare machine
run: sudo /root/bin/prep.sh

# Pin the benchmark run to core 0 and run all benchmarks at elevated priority.
- name: Run cargo bench
run: |
taskset -c 0 nice -n -20 \
cargo "+$TOOLCHAIN" bench --features bench -- --noplot | tee results.txt
# Pin all but neqo-bin benchmarks to CPU 0. neqo-bin benchmarks run
# both a client and a server, thus benefiting from multiple CPU cores.
#
# Run all benchmarks at elevated priority.
taskset -c 0 nice -n -20 cargo "+$TOOLCHAIN" bench --workspace --exclude neqo-bin --features bench -- --noplot | tee results.txt
nice -n -20 cargo "+$TOOLCHAIN" bench --package neqo-bin --features bench -- --noplot | tee -a results.txt
# Pin the transfer benchmark to core 0 and run it at elevated priority inside perf.
# Work around https://github.com/flamegraph-rs/flamegraph/issues/248 by passing explicit perf arguments.
- name: Profile cargo bench transfer
run: |
taskset -c 0 nice -n -20 \
cargo "+$TOOLCHAIN" flamegraph -v -c "$PERF_CMD" --features bench --bench transfer -- \
--bench --exact "Run multiple transfers with varying seeds" --noplot
- name: Profile client/server transfer
run: |
{ mkdir server; \
cd server; \
taskset -c 0 nice -n -20 \
cargo "+$TOOLCHAIN" flamegraph -v -c "$PERF_CMD" \
--bin neqo-server -- --db ../test-fixture/db "$HOST:4433" || true; } &
mkdir client; \
cd client; \
time taskset -c 1 nice -n -20 \
cargo "+$TOOLCHAIN" flamegraph -v -c "$PERF_CMD" \
--bin neqo-client -- --output-dir . "https://$HOST:4433/$SIZE"
killall -INT neqo-server
cd ${{ github.workspace }}
[ "$(wc -c < client/"$SIZE")" -eq "$SIZE" ] || exit 1
# Compare various configurations of neqo against msquic, and gather perf data
# during the hyperfine runs.
- name: Compare neqo and msquic
env:
HOST: localhost
SIZE: 1073741824 # 1 GB
HOST: 127.0.0.1
PORT: 4433
SIZE: 134217728 # 128 MB
run: |
TMP=$(mktemp -d)
# Make a cert and key for msquic.
openssl req -nodes -new -x509 -keyout "$TMP/key" -out "$TMP/cert" -subj "/CN=DOMAIN" 2>/dev/null
# Make a test file for msquic to serve.
truncate -s "$SIZE" "$TMP/$SIZE"
# Define the commands to run for each client and server.
declare -A client_cmd=(
["neqo"]="target/release/neqo-client _cc _pacing --output-dir . -o -a hq-interop -Q 1 https://$HOST:$PORT/$SIZE"
["msquic"]="msquic/build/bin/Release/quicinterop -test:D -custom:$HOST -port:$PORT -urls:https://$HOST:$PORT/$SIZE"
)
declare -A server_cmd=(
["neqo"]="target/release/neqo-server _cc _pacing -o -a hq-interop -Q 1 $HOST:$PORT 2> /dev/null"
["msquic"]="msquic/build/bin/Release/quicinteropserver -root:$TMP -listen:$HOST -port:$PORT -file:$TMP/cert -key:$TMP/key -noexit > /dev/null || true"
)
# Replace various placeholders in the commands with the actual values.
# Also generate an extension to append to the file name.
function transmogrify {
CMD=$1
local cc=$2
local pacing=$3
if [ "$cc" != "" ]; then
CMD=${CMD//_cc/--cc $cc}
EXT="-$cc"
fi
if [ "$pacing" == "on" ]; then
CMD=${CMD//_pacing/}
EXT="$EXT-pacing"
else
CMD=${CMD//_pacing/--no-pacing}
EXT="$EXT-nopacing"
fi
}
for server in msquic neqo; do
for client in msquic neqo; do
# msquic doesn't let us configure the congestion control or pacing.
if [ "$client" == "msquic" ] && [ "$server" == "msquic" ]; then
cc_opt=("")
pacing_opt=("")
else
cc_opt=("reno" "cubic")
pacing_opt=("on" "")
fi
for cc in "${cc_opt[@]}"; do
for pacing in "${pacing_opt[@]}"; do
# Make a tag string for this test, for the results.
TAG="$client,$server,$cc,$pacing"
echo "Running benchmarks for $TAG" | tee -a comparison.txt
transmogrify "${server_cmd[$server]}" "$cc" "$pacing"
# shellcheck disable=SC2086
taskset -c 0 nice -n -20 \
perf $PERF_OPT -o "$client-$server$EXT.server.perf" $CMD &
PID=$!
transmogrify "${client_cmd[$client]}" "$cc" "$pacing"
# shellcheck disable=SC2086
taskset -c 1 nice -n -20 \
perf $PERF_OPT -o "$client-$server$EXT.client.perf" \
hyperfine -N --output null -w 1 -s "sleep 1" -n "$TAG" -u millisecond --export-markdown step.md "$CMD" |
tee -a comparison.txt
echo >> comparison.txt
kill $PID
cat step.md >> steps.md
# Sanity check the size of the last retrieved file.
[ "$(wc -c <"$SIZE")" -eq "$SIZE" ] || exit 1
done
done
done
done
# Merge the results tables generated by hyperfine into a single table.
echo "Transfer of $SIZE bytes over loopback." > comparison.md
awk '(!/^\| Command/ || !c++) && (!/^\|:/ || !d++)' < steps.md |\
sed -E 's/`//g; s/^\|:/\|:---\|:---\|:---\|:/g; s/,/ \| /g; s/^\| Command/\| Client \| Server \| CC \| Pacing/g' >> comparison.md
rm -r "$TMP"
# Re-enable turboboost, hyperthreading and use powersave governor.
- name: Restore machine
run: sudo /root/bin/unprep.sh
if: success() || failure() || cancelled()

- name: Convert for profiler.firefox.com
- name: Post-process perf data
run: |
perf script -i perf.data -F +pid > transfer.perf &
perf script -i client/perf.data -F +pid > client.perf &
perf script -i server/perf.data -F +pid > server.perf &
for f in *.perf; do
# Convert for profiler.firefox.com
perf script -i "$f" -F +pid > "$f.fx" &
# Generate perf reports
perf report -i "$f" --no-children --stdio > "$f.txt" &
# Generate flamegraphs
flamegraph --perfdata "$f" --palette rust -o "${f//.perf/.svg}" &
done
wait
mv flamegraph.svg transfer.svg
mv client/flamegraph.svg client.svg
mv server/flamegraph.svg server.svg
rm neqo.svg
- name: Generate perf reports
run: |
perf report -i perf.data --no-children --stdio > transfer.perf.txt &
perf report -i client/perf.data --no-children --stdio > client.perf.txt &
perf report -i server/perf.data --no-children --stdio > server.perf.txt &
wait
- name: Format results as Markdown
id: results
run: |
{
echo "### Benchmark results"
echo
} > results.md
SHA=$(cat target/criterion/baseline-sha.txt)
SHA=$(cat target/criterion/baseline-sha.txt || true)
if [ -n "$SHA" ]; then
{
echo "Performance differences relative to $SHA."
Expand All @@ -129,6 +202,11 @@ jobs:
-e 's/^([a-z0-9].*)$/* **\1**/gi' \
-e 's/(change:[^%]*% )([^%]*%)(.*)/\1**\2**\3/gi' \
>> results.md
{
echo "### Client/server transfer results"
cat comparison.md
} >> results.md
cat results.md > "$GITHUB_STEP_SUMMARY"
- name: Remember main-branch push URL
if: github.ref == 'refs/heads/main'
Expand All @@ -155,6 +233,7 @@ jobs:
path: |
*.svg
*.perf
*.perf.fx
*.txt
results.*
target/criterion*
Expand Down
Loading

0 comments on commit e2e54fa

Please sign in to comment.