Skip to content

Commit

Permalink
Run benchmark tests "logic only" on Travis CI
Browse files Browse the repository at this point in the history
The benchmark tests are run only once without reports.
  • Loading branch information
sbellem committed May 20, 2020
1 parent f2a9ac5 commit 2821aa0
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 30 deletions.
15 changes: 15 additions & 0 deletions .ci/run-benchmark-tests-logic-only.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -ev

if [ -z $1 ]; then
tag=$IMAGE_TAG
else
tag=$1
fi

docker run -it $tag \
pytest --verbose \
--benchmark-disable \
-m skip_bench \
benchmark/
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@ sharedata/

.ci/deploy_key
.ci/deploy_key.pub

# benchmark
.benchmarks
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ jobs:
install: .ci/pull-or-build-image.sh
script: .ci/run-tests.sh
after_success: .ci/upload-coverage-report.sh
- name: Benchmark Tests - logic only
env:
- SETUP_EXTRAS: "tests"
install: .ci/pull-or-build-image.sh
script: .ci/run-benchmark-tests-logic-only.sh
- if: |
type = pull_request OR \
repo != initc3/HoneyBadgerMPC OR \
Expand Down
61 changes: 60 additions & 1 deletion benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,63 @@
* Add a file in this folder with the prefix `test_benchmark` in the name.
* Follow other benchmarks already written on how to write benchmark code. You can also refer to the [official documentation](https://pytest-benchmark.readthedocs.io/en/latest/).
* To run all benchmarks: `pytest -v benchmark`
* To run a single benchmark: `pytest -v benchmark -k <benchmark_method_name>`
* To run a single benchmark: `pytest -v benchmark -k <benchmark_method_name>`

## Disabling Benchmark Tests
It's possible to test only the logic of the benchmark tests with the
[`--benchmark-disable`](https://pytest-benchmark.readthedocs.io/en/latest/usage.html#commandline-options) option.

> Benchmarked functions are only ran once and no stats are reported.
> Use this if you want to run the test but don't do any benchmarking.
Example:

```shell
$ pytest -v --benchmark-disable benchmark/
```

## Reducing Parametrization
Many tests are parametrized such that the same logic will be executed
multiple times, for different parameter values. In order to allow for
only testing one set of parameter values, meaning running a particular
test only once, as opposed to running it multiple times with different
parameter values, the custom "boolean" `pytest` marker, `skip_bench` is
available. To set `skip_bench` to `True` use the option
`-m skip_bench`:

```shell
$ pytest -v -m skip_bench benchmark/
```

For instance, without `-m skip_bench`:

```shell
$ pytest -v benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft

benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[1]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[3]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[5]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[10]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[25]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[33]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[50]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[100]
benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[256]
```

and with `-m skip_bench`:

```shell
pytest -v -m skip_bench benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft

benchmark/test_benchmark_reed_solomon.py::test_benchmark_gao_robust_decode_fft[1]
```

## Logic Only Benchmark Tests Execution
To only check whether the benchmark tests actually run properly,
without benchmarking them and without testing for many sets of
paramter values, use both `--benchmark-disable` and `-m skip_bench`:

```shell
$ pytest -v --benchmark-disable -m skip_bench benchmark/
```
10 changes: 5 additions & 5 deletions benchmark/test_benchmark_hbavss.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from contextlib import ExitStack
from random import randint

from pytest import mark
from pytest import mark, param

from honeybadgermpc.betterpairing import G1, ZR
from honeybadgermpc.elliptic_curve import Subgroup
Expand All @@ -24,7 +24,7 @@ def get_avss_params(n, t):
@mark.parametrize(
"t, k",
[
(1, 5),
param(1, 5, marks=mark.skip_bench),
(3, 5),
(5, 5),
(16, 5),
Expand Down Expand Up @@ -70,7 +70,7 @@ def _prog():
@mark.parametrize(
"t, k",
[
(1, 5),
param(1, 5, marks=mark.skip_bench),
(3, 5),
(5, 5),
(16, 5),
Expand Down Expand Up @@ -113,7 +113,7 @@ def _prog():
@mark.parametrize(
"t, k",
[
(1, 5),
param(1, 5, marks=mark.skip_bench),
(3, 5),
(5, 5),
(16, 5),
Expand Down Expand Up @@ -160,7 +160,7 @@ def _prog():
@mark.parametrize(
"t, k",
[
(1, 5),
param(1, 5, marks=mark.skip_bench),
(3, 5),
(5, 5),
(16, 5),
Expand Down
15 changes: 12 additions & 3 deletions benchmark/test_benchmark_jubjub.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pytest import mark
from pytest import mark, param

from honeybadgermpc.elliptic_curve import Jubjub, Point
from honeybadgermpc.progs.jubjub import SharedPoint, share_mul
Expand Down Expand Up @@ -32,7 +32,11 @@
TEST_CURVE,
) # noqa: E501

ALL_BIT_NUMBERS = [int(f"0b{'1' * i}", 2) for i in [1, 64, 128]]

ALL_BIT_NUMBERS = [
param(int(f"0b{'1' * i}", 2), marks=(mark.skip_bench if i == 1 else []))
for i in [1, 64, 128]
]

n, t = 4, 1
k = 50000
Expand All @@ -45,6 +49,7 @@ def run_benchmark(
runner(prog, n, t, preprocessing, k, mixins)


@mark.skip_bench
def test_benchmark_shared_point_add(benchmark_runner):
async def _prog(context):
result = SharedPoint.from_point(context, TEST_POINT)
Expand All @@ -54,6 +59,7 @@ async def _prog(context):
run_benchmark(benchmark_runner, _prog)


@mark.skip_bench
def test_benchmark_shared_point_double(benchmark_runner):
async def _prog(context):
result = SharedPoint.from_point(context, TEST_POINT)
Expand Down Expand Up @@ -87,7 +93,10 @@ async def _prog(context):
run_benchmark(benchmark_runner, _prog)


@mark.parametrize("bit_length", list(range(64, 257, 64)))
@mark.parametrize(
"bit_length",
[param(i, marks=mark.skip_bench) if i == 64 else i for i in range(64, 257, 64)],
)
def test_benchmark_share_mul(bit_length, benchmark_runner):
p = TEST_POINT

Expand Down
7 changes: 5 additions & 2 deletions benchmark/test_benchmark_mimc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from random import randint

from pytest import mark
from pytest import mark, param

from honeybadgermpc.elliptic_curve import Jubjub
from honeybadgermpc.progs.mimc import mimc_mpc_batch
Expand Down Expand Up @@ -34,7 +34,10 @@


# All iterations take around 30min total.
@mark.parametrize("batch_size", [10 ** i for i in range(4)])
@mark.parametrize(
"batch_size",
[param(10 ** i, marks=mark.skip_bench) if i == 0 else 10 ** i for i in range(4)],
)
def test_benchmark_mimc_mpc_batch(batch_size, benchmark_runner):
async def _prog(context):
xs = [context.preproc.get_rand(context) for _ in range(batch_size)]
Expand Down
22 changes: 17 additions & 5 deletions benchmark/test_benchmark_polynomial.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from random import randint

from pytest import mark
from pytest import mark, param

from honeybadgermpc.ntl import fft_interpolate, lagrange_interpolate
from honeybadgermpc.polynomial import get_omega
Expand All @@ -19,26 +19,38 @@ def get_points(n, galois_field):
return x, y, points, omega


@mark.parametrize("n", [2 ** i for i in range(4, 11, 2)])
@mark.parametrize(
"n",
[param(2 ** i, marks=(mark.skip_bench if i == 4 else [])) for i in range(4, 11, 2)],
)
def test_benchmark_lagrange_interpolate_python(benchmark, n, galois_field, polynomial):
_, _, points, _ = get_points(n, galois_field)
benchmark(polynomial.interpolate, points)


@mark.parametrize("n", [2 ** i for i in range(4, 11, 2)])
@mark.parametrize(
"n",
[param(2 ** i, marks=(mark.skip_bench if i == 4 else [])) for i in range(4, 11, 2)],
)
def test_benchmark_lagrange_interpolate_cpp(benchmark, n, galois_field):
x, y, _, _ = get_points(n, galois_field)
p = galois_field.modulus
benchmark(lagrange_interpolate, x, y, p)


@mark.parametrize("n", [2 ** i for i in range(4, 21, 4)])
@mark.parametrize(
"n",
[param(2 ** i, marks=(mark.skip_bench if i == 4 else [])) for i in range(4, 21, 4)],
)
def test_benchmark_fft_interpolate_python(benchmark, n, galois_field, polynomial):
_, y, _, omega = get_points(n, galois_field)
benchmark(polynomial.interpolate_fft, y, omega)


@mark.parametrize("n", [2 ** i for i in range(4, 21, 4)])
@mark.parametrize(
"n",
[param(2 ** i, marks=(mark.skip_bench if i == 4 else [])) for i in range(4, 21, 4)],
)
def test_benchmark_fft_interpolate_cpp(benchmark, n, galois_field, polynomial):
_, y, _, omega = get_points(n, galois_field)
n = len(y)
Expand Down
11 changes: 8 additions & 3 deletions benchmark/test_benchmark_preprocessing.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
from pytest import mark
from pytest import mark, param

from honeybadgermpc.preprocessing import PreProcessedElements


@mark.parametrize("n,t,k", [(4, 1, 1024), (16, 5, 512), (50, 15, 256)])
@mark.parametrize(
"n,t,k", [param(4, 1, 1024, marks=mark.skip_bench), (16, 5, 512), (50, 15, 256)]
)
def test_benchmark_generate_rands(benchmark, n, t, k):
pp_elements = PreProcessedElements()
pp_elements.clear_preprocessing()
benchmark(pp_elements.generate_rands, k, n, t)


@mark.parametrize("n,t,k,z", [(4, 1, 64, 64), (16, 5, 32, 32), (61, 20, 32, 32)])
@mark.parametrize(
"n,t,k,z",
[param(4, 1, 64, 64, marks=mark.skip_bench), (16, 5, 32, 32), (61, 20, 32, 32)],
)
def test_benchmark_generate_powers(benchmark, n, t, k, z):
pp_elements = PreProcessedElements()
pp_elements.clear_preprocessing()
Expand Down
6 changes: 3 additions & 3 deletions benchmark/test_benchmark_rbc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import os
from random import randint

from pytest import mark
from pytest import mark, param

from honeybadgermpc.broadcast.reliablebroadcast import reliablebroadcast


@mark.parametrize(
"t, msglen",
[
(1, 200),
param(1, 200, marks=mark.skip_bench),
(1, 10000),
(3, 200),
(3, 10000),
Expand Down Expand Up @@ -45,7 +45,7 @@ def _prog():
@mark.parametrize(
"t, msglen",
[
(1, 200),
param(1, 200, marks=mark.skip_bench),
(1, 10000),
(3, 200),
(3, 10000),
Expand Down
12 changes: 8 additions & 4 deletions benchmark/test_benchmark_reed_solomon.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from random import randint

from pytest import mark
from pytest import mark, param

from honeybadgermpc.elliptic_curve import Subgroup
from honeybadgermpc.field import GF
from honeybadgermpc.polynomial import EvalPoint, polynomials_over
from honeybadgermpc.reed_solomon import GaoRobustDecoder


@mark.parametrize("t", [1, 3, 5, 10, 25, 33, 50, 100, 256])
@mark.parametrize(
"t", [param(1, marks=mark.skip_bench), 3, 5, 10, 25, 33, 50, 100, 256]
)
def test_benchmark_gao_robust_decode(benchmark, t, galois_field):
n = 3 * t + 1
galois_field = GF(Subgroup.BLS12_381)
Expand All @@ -34,11 +36,13 @@ def test_benchmark_gao_robust_decode(benchmark, t, galois_field):
# assert set(faults) == set(decoded_faults)


@mark.parametrize("t", [1, 3, 5, 10, 25, 33, 50, 100, 256])
@mark.parametrize(
"t", [param(1, marks=mark.skip_bench), 3, 5, 10, 25, 33, 50, 100, 256]
)
def test_benchmark_gao_robust_decode_fft(benchmark, t, galois_field):
n = 3 * t + 1
galois_field = GF(Subgroup.BLS12_381)
point = EvalPoint(galois_field, n, use_fft=True)
point = EvalPoint(galois_field, n, use_omega_powers=True)
omega = point.omega.value
p = galois_field.modulus
dec = GaoRobustDecoder(t, point)
Expand Down
4 changes: 2 additions & 2 deletions benchmark/test_benchmark_refinement.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from pytest import mark
from pytest import mark, param

from honeybadgermpc.progs.random_refinement import refine_randoms


@mark.parametrize("n", [4, 10, 16, 50, 100])
@mark.parametrize("n", [param(4, marks=mark.skip_bench), 10, 16, 50, 100])
def test_benchmark_random_refinement(benchmark, n, galois_field):
t = (n - 1) // 3
random_shares_int = [galois_field.random().value for _ in range(n)]
Expand Down
5 changes: 4 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ log_file_level = DEBUG
norecursedirs = charm benchmark

# depends on pytest-env plugin ()
env =
env =
PYTHONASYNCIODEBUG=1

markers =
skip_bench: mark a test to be run when skipping benchmarking (select with '-m skip_bench' and deselect with '-m not skip_bench"')
2 changes: 1 addition & 1 deletion tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,6 @@ def _setup():
def _work():
loop.run_until_complete(program_runner.join())

benchmark(_work, setup=_setup)
benchmark.pedantic(_work, setup=_setup)

return _benchmark_runner

0 comments on commit 2821aa0

Please sign in to comment.