Skip to content

Commit 7fa2775

Browse files
committed
Run performance benchmarks as CI job
To guard against performance regressions introduced by changes, run a fixed set (with this commit: the LLBMC benchmark suite) of benchmarks on each pull request.
1 parent e0afa1f commit 7fa2775

File tree

2 files changed

+156
-0
lines changed

2 files changed

+156
-0
lines changed

Diff for: .github/workflows/performance-compare.py

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/usr/bin/env python3
2+
3+
from collections import defaultdict
4+
5+
import csv
6+
import sys
7+
8+
9+
def compare(results):
10+
differences = []
11+
12+
for bm in results:
13+
if not results[bm].get("base"):
14+
print("Missing base result for " + bm)
15+
differences.append(bm)
16+
continue
17+
if not results[bm].get("pr"):
18+
print("Missing pr result for " + bm)
19+
differences.append(bm)
20+
continue
21+
22+
b = results[bm]["base"]
23+
p = results[bm]["pr"]
24+
25+
if b["Result"] != p["Result"]:
26+
print("Verification results differ for " + bm)
27+
differences.append(bm)
28+
continue
29+
30+
ut_base = float(b["usertime"])
31+
ut_pr = float(p["usertime"])
32+
if abs(ut_base - ut_pr) > 1.5:
33+
print("Usertime difference of more than 1.5 seconds for " + bm)
34+
differences.append(bm)
35+
36+
mem_base = int(b["maxmem"][:-2])
37+
mem_pr = int(p["maxmem"][:-2])
38+
if abs(mem_base - mem_pr) > 5 * 1024:
39+
print("Maxmem difference of more than 5 MB for " + bm)
40+
differences.append(bm)
41+
42+
return differences
43+
44+
45+
def main():
46+
base = sys.argv[1]
47+
pr = sys.argv[2]
48+
49+
results = defaultdict(defaultdict)
50+
51+
with open(base) as base_file, open(pr) as pr_file:
52+
base_reader = csv.DictReader(base_file)
53+
pr_reader = csv.DictReader(pr_file)
54+
55+
for b in base_reader:
56+
results[b["Benchmark"]]["base"] = b
57+
for p in pr_reader:
58+
results[p["Benchmark"]]["pr"] = p
59+
60+
differences = compare(results)
61+
62+
for d in differences:
63+
print("base: " + str(results[d]["base"]))
64+
print("pr: " + str(results[d]["pr"]))
65+
66+
return 1 if len(differences) else 0
67+
68+
69+
if __name__ == "__main__":
70+
rc = main()
71+
sys.exit(rc)

Diff for: .github/workflows/performance.yaml

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Performance benchmarking
2+
3+
on:
4+
pull_request:
5+
branches: [ develop ]
6+
7+
jobs:
8+
run-llbmc-benchmarks:
9+
runs-on: ubuntu-20.04
10+
steps:
11+
- uses: actions/checkout@v2
12+
with:
13+
submodules: recursive
14+
fetch-depth: 0
15+
- name: Fetch dependencies
16+
env:
17+
# This is needed in addition to -yq to prevent apt-get from asking for
18+
# user input
19+
DEBIAN_FRONTEND: noninteractive
20+
run: |
21+
sudo apt-get install --no-install-recommends -y build-essential flex bison maven ccache
22+
sudo apt-get install --no-install-recommends -y bmt poppler-utils texlive-latex-base texlive-pictures
23+
make -C src minisat2-download
24+
- name: Prepare ccache
25+
uses: actions/cache@v2
26+
with:
27+
path: .ccache
28+
key: ${{ runner.os }}-20.04-make-${{ github.ref }}-${{ github.sha }}-Performance
29+
restore-keys: |
30+
${{ runner.os }}-20.04-make-${{ github.ref }}
31+
${{ runner.os }}-20.04-make
32+
- name: ccache environment
33+
run: |
34+
echo "CCACHE_BASEDIR=$PWD" >> $GITHUB_ENV
35+
echo "CCACHE_DIR=$PWD/.ccache" >> $GITHUB_ENV
36+
- name: Zero ccache stats and limit in size
37+
run: ccache -z --max-size=500M
38+
- name: Build with make
39+
run: |
40+
make -C src CXX='ccache /usr/bin/g++' cbmc.dir goto-cc.dir -j2
41+
mkdir pr-bin
42+
cp src/cbmc/cbmc pr-bin/
43+
cp src/goto-cc/goto-cc pr-bin/
44+
cp .github/workflows/performance-compare.py pr-bin/
45+
echo "PR_BIN=$PWD/pr-bin" >> $GITHUB_ENV
46+
- name: Build base with make
47+
run: |
48+
git checkout -b ${{ github.ref }}
49+
git checkout ${{ github.base_ref }}
50+
git checkout -b base ${{ github.base_ref }}
51+
make -C src CXX='ccache /usr/bin/g++' cbmc.dir goto-cc.dir -j2
52+
mkdir base-bin
53+
cp src/cbmc/cbmc base-bin/
54+
cp src/goto-cc/goto-cc base-bin/
55+
echo "BASE_BIN=$PWD/base-bin" >> $GITHUB_ENV
56+
- name: Print ccache stats
57+
run: ccache -s
58+
- name: Run LLBMC benchmarks
59+
run: |
60+
git clone --depth=1 https://github.com/tautschnig/bmt.git bmt.git
61+
cd bmt.git/pkgs
62+
tar czf ../llbmc-bench.cprover-bm.tar.gz llbmc-bench
63+
cd ..
64+
cpbm unpack orig-src/llbmc-bench-vstte-2012.tgz llbmc-bench.cprover-bm.tar.gz
65+
cd llbmc-bench
66+
sed -i 's/\(ex36.*\)/\1 --unwind 11/' cprover/cbmc_opts
67+
export PATH=$BASE_BIN:$PATH
68+
cprover/rules -j2 table CONFIG=cbmc.base
69+
export PATH=$PR_BIN:$PATH
70+
cprover/rules -j2 table CONFIG=cbmc.pr
71+
# avoid downloading PGF as we use the Ubuntu package
72+
mkdir -p base pgfplots
73+
cpbm graph -s cprover/results.cbmc.base.csv cprover/results.cbmc.pr.csv
74+
pdftoppm -png results.cbmc.base_results.cbmc.pr-scatter.pdf scatter
75+
- uses: actions/upload-artifact@v2
76+
with:
77+
name: scatter.png
78+
path: bmt.git/llbmc-bench/scatter-1.png
79+
if-no-files-found: error
80+
- name: Compare results
81+
run: |
82+
cd bmt.git/llbmc-bench
83+
cut -d, -f2,3,5,10,13,17 cprover/results.cbmc.base.csv > base.csv
84+
cut -d, -f2,3,5,10,13,17 cprover/results.cbmc.pr.csv > pr.csv
85+
$PR_BIN/performance-compare.py base.csv pr.csv

0 commit comments

Comments
 (0)