diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml new file mode 100644 index 00000000..e8184b71 --- /dev/null +++ b/.github/workflows/benchmarks.yml @@ -0,0 +1,51 @@ +name: Benchmarks + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + name: Benchmark library + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Nargo + uses: noir-lang/noirup@v0.1.3 + with: + toolchain: 1.0.0-beta.0 + + - name: Install bb + run: | + npm install -g bbup + bbup -nv 1.0.0-beta.0 + + - name: Build Noir benchmark programs + run: nargo export + + - name: create the export directory + run: mkdir -p export + + - name: Generate gates report + run: ./scripts/build-gates-report.sh + env: + BACKEND: /home/runner/.bb/bb + + - name: Compare gates reports + id: gates_diff + uses: noir-lang/noir-gates-diff@1931aaaa848a1a009363d6115293f7b7fc72bb87 + with: + report: gates_report.json + summaryQuantile: 0.9 # only display the 10% most significant circuit size diffs in the summary (defaults to 20%) + + - name: Add gates diff to sticky comment + if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target' + uses: marocchino/sticky-pull-request-comment@v2 + with: + # delete the comment in case changes no longer impact circuit sizes + delete: ${{ !steps.gates_diff.outputs.markdown }} + message: ${{ steps.gates_diff.outputs.markdown }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1db5d1ed..fba3f1b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ on: env: CARGO_TERM_COLOR: always - MINIMUM_NOIR_VERSION: v0.36.0 + MINIMUM_NOIR_VERSION: v1.0.0-beta.0 jobs: noir-version-list: diff --git a/.gitignore b/.gitignore index f99b23da..1e8e74ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ target .vscode/launch.json +gates_report.json +export/*.* diff --git a/gates_report.json b/gates_report.json new file mode 100644 index 00000000..5d8657c4 --- /dev/null +++ b/gates_report.json @@ -0,0 +1,14 @@ +{"programs": [ +{"package_name": "test_add_BN.json", "functions": [{ + "acir_opcodes": 4, + "circuit_size": 20, + "gates_per_opcode": [ + 2, + 1, + 1, + 1 + ], + "name": "main" +}] +} +]} diff --git a/scripts/build-gates-report.sh b/scripts/build-gates-report.sh new file mode 100755 index 00000000..28f0a633 --- /dev/null +++ b/scripts/build-gates-report.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +set -e + +BACKEND=${BACKEND:-bb} + +cd $(dirname "$0")/../ + +artifacts_path="./export" +artifacts=$(ls $artifacts_path) + +echo "{\"programs\": [" > gates_report.json + +# Bound for checking where to place last parentheses +NUM_ARTIFACTS=$(ls -1q "$artifacts_path" | wc -l) + +ITER="1" +for artifact in $artifacts; do + ARTIFACT_NAME=$(basename "$artifact") + + GATES_INFO=$($BACKEND gates -b "$artifacts_path/$artifact") + MAIN_FUNCTION_INFO=$(echo $GATES_INFO | jq -r '.functions[0] | .name = "main"') + echo "{\"package_name\": \"$ARTIFACT_NAME\", \"functions\": [$MAIN_FUNCTION_INFO]" >> gates_report.json + + if (($ITER == $NUM_ARTIFACTS)); then + echo "}" >> gates_report.json + else + echo "}, " >> gates_report.json + fi + + ITER=$(( $ITER + 1 )) +done + +echo "]}" >> gates_report.json \ No newline at end of file diff --git a/src/benchmarks/bignum_bench.nr b/src/benchmarks/bignum_bench.nr new file mode 100644 index 00000000..0db2dada --- /dev/null +++ b/src/benchmarks/bignum_bench.nr @@ -0,0 +1,34 @@ +use crate::utils::u60_representation::U60Repr; + +use crate::bignum::BigNum; +use crate::bignum::BigNumTrait; + +use crate::params::BigNumParams; +use crate::params::BigNumParamsGetter; + +use crate::fields::bls12_381Fq::BLS12_381_Fq_Params; +use crate::fields::bn254Fq::BN254_Fq_Params; +use crate::fields::U256::U256Params; + +struct Test2048Params {} + +// See https://github.com/noir-lang/noir/issues/6172 + +type Fq = BigNum<3, 254, BN254_Fq_Params>; +type BN256 = BigNum<3, 257, U256Params>; +type BN381 = BigNum<4, 381, BLS12_381_Fq_Params>; +type BN2048 = BigNum<18, 2048, Test2048Params>; + +#[export] +fn test_add_BN() { + let mut a: Fq = BigNum::modulus(); + let mut b: Fq = BigNum::modulus(); + let mut expected: Fq = BigNum::modulus(); + + a.limbs[0] -= 1; + b.limbs[0] -= 1; + expected.limbs[0] -= 2; + + let result = a + b; + assert(result == expected); +} diff --git a/src/benchmarks/mod.nr b/src/benchmarks/mod.nr new file mode 100644 index 00000000..c1eddc0d --- /dev/null +++ b/src/benchmarks/mod.nr @@ -0,0 +1 @@ +mod bignum_bench; diff --git a/src/bignum.nr b/src/bignum.nr index 52002bd7..94f0e60c 100644 --- a/src/bignum.nr +++ b/src/bignum.nr @@ -6,7 +6,8 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod, diff --git a/src/fns/constrained_ops.nr b/src/fns/constrained_ops.nr index 758e23dc..30ded4ea 100644 --- a/src/fns/constrained_ops.nr +++ b/src/fns/constrained_ops.nr @@ -5,7 +5,8 @@ use crate::fns::{ unconstrained_helpers::{ __add_with_flags, __neg_with_flags, __sub_with_flags, __validate_gt_remainder, __validate_in_field_compute_borrow_flags, - }, unconstrained_ops::{__div, __mul, __udiv_mod}, + }, + unconstrained_ops::{__div, __mul, __udiv_mod}, }; /** diff --git a/src/lib.nr b/src/lib.nr index fa8840ff..f379afdd 100644 --- a/src/lib.nr +++ b/src/lib.nr @@ -21,3 +21,5 @@ pub use runtime_bignum::RuntimeBigNum; // Tests mod tests; + +mod benchmarks; diff --git a/src/runtime_bignum.nr b/src/runtime_bignum.nr index 0325ca54..ec141ebd 100644 --- a/src/runtime_bignum.nr +++ b/src/runtime_bignum.nr @@ -5,7 +5,8 @@ use crate::fns::{ constrained_ops::{ add, assert_is_not_equal, conditional_select, derive_from_seed, div, eq, mul, neg, sub, udiv, udiv_mod, umod, validate_in_field, validate_in_range, - }, expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, + }, + expressions::{__compute_quadratic_expression, evaluate_quadratic_expression}, serialization::{from_be_bytes, to_le_bytes}, unconstrained_ops::{ __add, __batch_invert, __batch_invert_slice, __derive_from_seed, __div, __eq, __invmod,