---
# System prepended metadata

title: Benchmarking pairing-friendly elliptic curves libraries

---

# Benchmarking pairing-friendly elliptic curves libraries
*last benchmark update: 29/01/21*

There are several pairing-friendly elliptic curves libraries used in zero-knowledge proofs (ZKP) projects. Typically, the most important elliptic curve operations in ZKP schemes are *"multi scalar multiplication"* (***MSM***) and *"pairing product"* (***PP***). This writeup is a try to benchmark and compare the building blocks of these operations in two different architechtures.
In fact, since ***MSM*** and ***PP*** are size-dependant, we focus on timings of *mixed addition in G1/G2*, *doubling in G1/G2*, *Miller loop* and *Final exponentiation*.

The libraries are written in different languages with different software and mathematical optimizations, and with more or less assembly code.

The target curves are: `BN254`, `BLS12-381`, `BLS12-377` and `BW6-761`.

The chosen libraries are:
| library     | benchmarked curves |original authors    | programming language  | license  | zkp/blockahin project |
|-------------|---- |------------|-----------|----------|---|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto)        |`BN254, BLS12-381, BLS12-377, BW6-761` |[Consensys](https://www.consensys.net/)   |Go     |[Apache-2.0](https://github.com/ConsenSys/gnark-crypto/blob/master/LICENSE)  | [gnark](https://github.com/ConsenSys/gnark) |
|[kilic](https://github.com/kilic?tab=repositories)/<curve>|`BN254, BLS12-381, BLS12-377, BW6-761`|[Onur Kilic](https://github.com/kilic)  |Go     |[Apache-2.0](https://github.com/kilic/bls12-381/blob/master/LICENSE)  | [Geth](https://geth.ethereum.org/) (`BLS12-381`)|
|[geth/crypto](https://github.com/ethereum/go-ethereum/tree/master/crypto)/<curve> |`BN254, BLS12-381` |[go-ethereum](https://geth.ethereum.org/)    |Go     |[LGPL-3.0](https://github.com/ethereum/go-ethereum/blob/master/COPYING)| [Geth](https://geth.ethereum.org/)|
|[arkworks-rs/curves](https://github.com/arkworks-rs/curves) <br> (*fromerly zexe*) |`BN254, BLS12-381, BLS12-377, BW6-761` |[arkworks-rs](http://arkworks.rs) | Rust* | [MIT/Apache-2.0](https://github.com/arkworks-rs/curves/blob/master/LICENSE-APACHE) | [Celo](https://celo.org/), [Aleo](https://aleo.org/) (`BLS12-377, BW6-761`)|
|[celo-org/zexe](https://github.com/celo-org/zexe)<br> (*based on arkworks*) |`BW6-761` |[celo-org](https://celo.org/) | Rust** | [MIT/Apache-2.0](https://github.com/celo-org/zexe/blob/master/LICENSE-APACHE) | [Celo](https://celo.org/) (`BW6-761`)|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)| `BLS12-381`    |[zkcrypto](https://github.com/zkcrypto)    |Rust | [MIT/Apache-2.0](https://github.com/zkcrypto/bls12_381/blob/main/COPYRIGHT)| [zcash](https://z.cash/), [Dusk](https://dusk.network/)|
|[mcl](https://github.com/herumi/mcl)| `BN254, BLS12-381`         | [MITSUNARI Shigeo](http://herumi.in.coocan.jp/) |C++  | [*modified* BSD-3-Clause](https://github.com/herumi/mcl#license)| [loopring](https://loopring.org/#/) (`BN254`), [DFINITY](https://dfinity.org/) (`BLS12-381`)|
|[blst](https://github.com/supranational/blst)| `BLS12-381`         | [Supranational](https://www.supranational.net/) |C      |[Apache-2.0](https://github.com/supranational/blst/blob/master/LICENSE) | [filecoin](https://filecoin.io/)|
| [relic](https://github.com/relic-toolkit/relic)|`BLS12-381` | [Diego F. Aranha](https://sites.google.com/site/dfaranha/) | C | [Apache-2.0/LGPL-2.1](https://github.com/relic-toolkit/relic/blob/master/LICENSE) | [Chia](https://www.chia.net/)|
|[libff](https://github.com/scipr-lab/libff)<br>(*develop branch*) | `BN254, BLS12-381`        | [SCIPR Lab](http://www.scipr-lab.org/)     | C++    |[MIT](https://github.com/scipr-lab/libff/blob/develop/LICENSE) | [libsnark](https://github.com/scipr-lab/libsnark)|
|[zk-swap-libff](https://github.com/EYBlockchain/zk-swap-libff)<br>(*based on libff*)| `BLS12-377, BW6-761`        | [EYBlockchain](https://blockchain.ey.com/)     | C++    |[MIT](https://github.com/EYBlockchain/zk-swap-libff/blob/ey/LICENSE) | [zk-swap-libsnark](https://github.com/EYBlockchain/zk-swap-libsnark)|
|[constantine](https://github.com/mratsim/constantine)| `BN254, BLS12-381, BLS12-377`        | [Mamy Ratsimbazafy](https://github.com/mratsim)     | Nim    |[MIT/Apache-2.0](https://github.com/mratsim/constantine/blob/master/LICENSE-APACHEv2) | |


\* assembly is disabled by default in `arkworks-rs`. To enable asm in benchmarks, e.g.: `RUSTFLAGS="-C target    -feature=+bmi2,+adx" cargo +nightly bench bls12_381::full_pairing --features asm`.

\** assembly is disabled by default in `celo-org/zexe`. To enable asm in benchmark on `BW6-761`curve: `RUSTFLAGS="-C target-feature=+bmi2,+adx" cargo +nightly  bench pairing --features "force_bw6_asm bw6_761"`

## BN254
### benchmark on AWS z1d.3xlarge (**3.4 GHz Intel Xeon**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing

| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[mcl](https://github.com/herumi/mcl/) (*BN_SNARK1*)|	C++	|0.4765|	0.2137|	0.2628|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254)(*bn254*)|Go |	0.4890|	0.2321|	0.2569|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|0.6471|	0.2934|	0.3424|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	0.8454|	0.3990|	0.4464|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|Rust|	1.0655|	0.4597|	0.6058|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	1.1915|	0.5265|	0.6649|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	1.3013|	0.4874|	0.8139|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/alt_bn128)(*alt_bn128*)|	C++|	2.1000|	0.6500|	1.4500|
|[geth/google](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/google)(*bn256*)|	Go|	11.4304|	4.1681|	7.2622|


![](https://i.imgur.com/p9vhdai.png)
*<center><sub><sup>(geth/google is discarded in this figure as it is too slow)</sub></sup></center>*


#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[mcl](https://github.com/herumi/mcl/) (*BN_SNARK1*)|	C++	|216	|	158|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254)(*bn254*)|Go |	231	|	143|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|237	|	151|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	315	|	228|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	413	|	205|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	472	|	253|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/alt_bn128)(*alt_bn128*)|	C++|	4236	|	2800|
|[geth/google](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/google)(*bn256*)|	Go|	8196	|	4102|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|Rust|	^|^	|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/jYBtX9I.png)
*<center><sub><sup>(geth/google and libff are discarded in this figure as they are too slow)</sub></sup></center>*

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[mcl](https://github.com/herumi/mcl/) (*BN_SNARK1*)|	C++	|594	|	374|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254)(*bn254*)|Go |	605	|	362|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|1035	|	481|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	1192	|	732|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	1378	|	593|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	1738	|	732|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/alt_bn128)(*alt_bn128*)|	C++|	6508	|	4533|
|[geth/google](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/google)(*bn256*)|	Go|	19549	|	9370|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/ZArRc5Z.png)
*<center><sub><sup>(geth/google and libff are discarded in this figure as they are too slow)</sub></sup></center>*

### benchmark on AWS c5a.2xlarge (**2.7 GHz AMD EPYC 7R32**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing
| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254) (*bn254*)|	Go	|0.5889|	0.2795|	0.3094|
|[mcl](https://github.com/herumi/mcl/)(*BN_SNARK1*)|	C++|	0.6085|	0.3375|	0.2710|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|0.9029|	0.4100|	0.4772|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	1.0362|	0.5063|	0.5299|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|	Rust|	1.3271|	0.5583|	0.7688|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	1.3834|	0.6201|	0.7633|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	1.4720|	0.5569|	0.9150|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/alt_bn128)(*alt_bn128*)|	C++|	2.800|	1.300|	1.500|
|[geth/google](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/google)(*bn256*)|	Go|	13.3843|	4.7476|	8.63662|


![](https://i.imgur.com/NnbSrX3.png)
*<center><sub><sup>(geth/google is discarded in this figure as it is too slow)</sub></sup></center>*

#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[mcl](https://github.com/herumi/mcl/) (*BN_SNARK1*)|	C++	|264	|209|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254)(*bn254*)|Go |	294	|173|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|349	|224|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	380	|297|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	495	|258|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	514	|290|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|Rust|	^|^	|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/p5BskPi.png)
*<center><sub><sup>(geth/google and libff are discarded in this figure as they are too slow)</sub></sup></center>*

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254)(*bn254*)|Go |	696	|425|
|[mcl](https://github.com/herumi/mcl/) (*BN_SNARK1*)|	C++	|735	|461|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bn254)(*bn254*)|	Rust|	1259|	820|
|[constantine](https://github.com/mratsim/constantine) (*BN254_Snarks*)|	Nim|1454	|691|
|[kilic/bn254](https://github.com/kilic/bn254)|	Go|	1736	|781|
|[geth/cloudflare](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare)(*bn256*)|	Go|	1912	|841|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bn254) (*bn254*)|Rust|	^|^	|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/s347B0L.png)
*<center><sub><sup>(geth/google and libff are discarded in this figure as they are too slow)</sub></sup></center>*

## BLS12-381
### benchmark on AWS z1d.3xlarge (**3.4 GHz Intel Xeon**)
> with hyperthreading, turbo and frequency scaling disabled.
>

#### Pairing
| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|0.6116|	0.2642|	0.3474|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|0.6794|	0.2864|	0.3930|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	0.7078|	0.3320|	0.3758|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|	Go|	0.8594|	0.3690|	0.4903|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|	Nim|0.9062|	0.3561|	0.5210|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	1.3149|	0.5780|	0.7369|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|Rust|	1.3271|	0.5583|	0.7688|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	1.3494|	1.5528|	0.7965|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	1.5886|	0.4971|	1.0914|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	1.6218|	0.6931|	0.9287|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/bls12_381)(*bls12_381*)|	C++|	3.9000|	1.5000|	2.4000|

![](https://i.imgur.com/nJJLx9J.png)

#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	387	|	245|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|	Nim|416	|	269|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|421	|	309|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|474	|	287|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|	Go|	558	|	282|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	672	|	414|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	787	|	565|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	789	|	383|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	938	|	674|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/bls12_381)(*bls12_381*)|	C++|	4183	|	3001|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*


![](https://i.imgur.com/huNSslo.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	1123	|	681|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|1164	|	728|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|1293	|	674|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|	Nim|1535	|	781|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|	Go|	1846	|	791|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	2126	|	1465|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	2143	|	1302|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	2537	|	1052|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	3071	|	2022|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/bls12_381)(*bls12_381*)|	C++|	7728	|	5361|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/hdyENJr.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

### benchmark on AWS c5a.2xlarge (**2.7 GHz AMD EPYC 7R32**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing
| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|0.7474|	0.3230|	0.4253|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|0.8437|	0.3508|	0.4929|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	0.8742|	0.4188|	0.4554|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|Go|	1.0757|	0.4568|	0.6189|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|Nim|1.3542|	0.5425|	0.7657|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	1.5581|	0.8760|	0.6821|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|	Rust|	1.5815|	0.6459|	0.9356|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	1.6970|	0.7044|	0.9926|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	1.8994|	0.8014|	1.0980|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	1.9324|	0.7978|	1.1346|
|[libff](https://github.com/scipr-lab/libff/tree/develop/libff/algebra/curves/bls12_381)(*bls12_381*)|	C++|	4.6000|	1.7000|	2.9000|

![](https://i.imgur.com/zHKp21e.png)

#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	511	|302|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|544	|401|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|623	|345|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|	Go|	683	|348|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|	Nim|692	|438|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	750	|547|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	933|	691|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	973	|463|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	1099	|803|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/g8LKjRD.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-381)(*bls12-381*)|	Go|	1410	|847|
|[mcl](https://github.com/herumi/mcl/) (*BLS12-381*)|	C++	|1489	|904|
|[blst](https://github.com/supranational/blst) (*BLS12-381*)|	C	|1621	|816|
|[kilic/bls12-381](https://github.com/kilic/bls12-381)|	Go|	2305	|1003|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_381)(*bls12_381*)|	Rust|	2412	|1516|
|[relic](https://github.com/relic-toolkit/relic) (*gmp-pbc-bls381 preset*)|	C|	2515	|1750|
|[constantine](https://github.com/mratsim/constantine) (*BLS12_381*)|	Nim|2543	|1261|
|[geth/bls12381](https://github.com/ethereum/go-ethereum/tree/master/crypto/bls12381)(*bls12381*, based on [kilic](https://github.com/kilic/bls12-381))|	Go|	2305	|1003|
|[zkcrypto/bls12_381](https://github.com/zkcrypto/bls12_381)|	Rust|	3543|	2344|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_381) (*bls12_381*)|Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/lPeWlB7.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

## BLS12-377
### benchmark on AWS z1d.3xlarge (**3.4 GHz Intel Xeon**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing

| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	        |Go   |	0.9184|	0.4080|	0.5104|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	0.9935|	0.4220|	0.5715|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|1.1160|	0.4430|	0.6467|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)  | Rust|	1.5775|	0.6550|	0.9225|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)       |	  Rust|	1.8769|	1.3463|	1.0855|
|[EYBlockchain/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bls12_377)(*bls12_377*)|	C++|	3.8000|	1.4000|	2.4000|

![](https://i.imgur.com/8T09wFW.png)

#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	        |Go   |	389	|	244|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|396	|	269|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	557	|	283|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)       |	  Rust|	767	|	410|
|[EYBlockchain/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bls12_377)(*bls12_377*)|	C++|	4136	|	3071|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)  | Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/sxHcdVp.png)

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	        |Go   |	1424	|	883|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|1877	|	1104|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	2109	|	909|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)       |	  Rust|	2723	|	1635|
|[EYBlockchain/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bls12_377)(*bls12_377*)|	C++|	7674	|	5284|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)  | Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/SOFUIqz.png)

### benchmark on AWS c5a.2xlarge (**2.7 GHz AMD EPYC 7R32**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing
| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	|Go|	1.1381|	0.5104|	0.6277|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	1.2539|	0.5245|	0.7229|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|1.6415|	0.9398|	0.65337|
|[arkworks+asm](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)|	Rust|	1.9030|	0.7747|	1.1283|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)|	Rust|	2.2305|	0.9726|	1.2579|
|[EYBlockchain/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bls12_377)(*bls12_377*)|	C++|	4.5000|	1.6000|	2.9000|

![](https://i.imgur.com/RF4Pqc7.png)

#### G1 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	        |Go   |	487	|301|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|664	|436|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	682	|344|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)       |	  Rust|	761	|546|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)  | Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/7kII9Jg.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

#### G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
|[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bls12-377) (*bls12-377*)	        |Go   |	1770|1082|
|[kilic/bls12-377](https://github.com/kilic/bls12-377)|	Go|	2669	|1164|
|[constantine](https://github.com/mratsim/constantine)(*BLS12_377*)|	Nim|2843	|1632|
|[arkworks](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)       |	  Rust|	3084	|1908|
|[arkworks(+asm)](https://github.com/arkworks-rs/curves/tree/master/bls12_377)(*bls12_377*)  | Rust|	^	|	^|
^ *benchmarking arkworks group madd/double with assembly feature enabled seems to output wrong timings.*

![](https://i.imgur.com/XXOuWCA.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

## BW6-761
### benchmark on AWS z1d.3xlarge (**3.4 GHz Intel Xeon**)
> with hyperthreading, turbo and frequency scaling disabled.

#### Pairing

| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
[kilic/bw6](https://github.com/kilic/bw6)|	Go|	2.8905|	1.7953|	1.0952|
[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bw6-761) (*bw6-761*)	|Go|	3.0681|	1.9453|	1.1228|
[celo-org/zexe](https://github.com/celo-org/zexe) (*bw6_761*)|	Rust|	3.6068|	1.8210|	1.7768|
[arkworks+asm](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust|	4.9032|	2.5087|	2.3946|
[arkworks](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust|	5.5040|	2.8590|	2.6450|
[EY/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bw6_761) (*bw6_761*)|	C++|	6.3000|	3.5000|	2.8000|

![](https://i.imgur.com/EUUqdd4.png)

#### G1/G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bw6-761) (*bw6-761*)|Go|	1410	|	862|
[celo-org/zexe](https://github.com/celo-org/zexe) (*bw6_761*)|	Rust       |	1404	|	945|
[arkworks+asm](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust|	1883	|	1213|
[kilic/bw6](https://github.com/kilic/bw6)|	Go        |	2101	|	9941|
[arkworks](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust       |	2193	|	1420|
[EY/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bw6_761) (*bw6_761*)|	C++|	7413	|	4683|

![](https://i.imgur.com/vrsgekV.png)

### benchmark on AWS c5a.2xlarge (**2.7 GHz AMD EPYC 7R32**)
> with hyperthreading, turbo and frequency scaling disabled.
>
#### Pairing
| ↓library     | language | Full pairing (ms)| Miller loop (ms) | Final exponentiation (ms) |
|-------------|----------|--------|-----------|----------|
[kilic/bw6](https://github.com/kilic/bw6)|	Go        |	3.4712|	2.2101|	1.2611|
[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bw6-761) (*bw6-761*)|Go|	3.5284|	2.0552|	1.4731|
[celo-org/zexe](https://github.com/celo-org/zexe) (*bw6_761*)|	Rust       |	4.4603|	2.2589|	2.2014|
[arkworks+asm](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust|	6.2773|	3.2008|	3.0765|
[arkworks](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust       |	6.8567|	3.5297|	3.3270|
[EY/libff](https://github.com/EYBlockchain/zk-swap-libff/tree/ey/libff/algebra/curves/bw6_761) (*bw6_761*)|	C++|	7.6000|	4.2000|	3.4000|

![](https://i.imgur.com/qbuOjrK.png)

#### G1/G2 mixed addition/doubling
| ↓library     | language | Mixed addition (ns)| doubling (ns) |
|-------------|----------|--------|-----------|
[celo-org/zexe](https://github.com/celo-org/zexe) (*bw6_761*)|	Rust       |	1698	|1156|
[gnark-crypto](https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bw6-761) (*bw6-761*)|Go|	1881	|1150|
[arkworks+asm](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust|	2363|	1591|
[kilic/bw6](https://github.com/kilic/bw6)|	Go        |	2525	|1197|
[arkworks](https://github.com/arkworks-rs/curves/tree/master/bw6_761) (*bw6_761*)|	Rust       |	2666|	1788|

![](https://i.imgur.com/knbinrU.png)
*<center><sub><sup>(libff is discarded in this figure as it is too slow)</sub></sup></center>*

### Conclusion
The libraries are implemented in different languages and some use more assembly code than others. Besides the different algorithmic and software optimizations used across, it should be noted also that some libraries target constant-time implementation for some operations making it de facto slower. However, it can be clear that [consensys/gnark-crypto](https://github.com/ConsenSys/gnark-crypto) is one of the fastest pairing-friendly elliptic curve libraries to be used in zkp projects with different curves.

---
<img style="float:left;width:90px;margin-right:20px;"
src="https://i.imgur.com/tYQ8i9r.png">*Author: [Youssef El Housni](https://www.linkedin.com/in/youssef-el-housni-412427108/).*


*I'm part of a research team at [ConsenSys](https://consensys.net/). If you are interested in our work ([fast finite field arithmetic](https://github.com/consensys/goff), [elliptic curve pairings](https://github.com/consensys/gnark-crypto), and [zero-knowledge proofs](https://github.com/consensys/gnark)), [give us a shout](mailto:zkteam@consensys.net).*
