Performance and Benchmarks
Circom
In summary:
Both native witness generation and proof generation are generally faster than snarkjs
in the browser, with potential speed improvements of up to 20 times.
However, performance varies across different circuits.
We recommend developers benchmark their custom circuits before selecting tools for app development.
- circom-witness-rs is not fully compatible with circom circuits. See: zkmopro/mopro#32.
- wasmer doesn't work in iOS. See: zkmopro/mopro#109.
iOS
Benchmarks on an iPhone 16 Pro (2024).
Witness generation | witnesscalc | circom-witnesscalc | wasmer | w2c | snarkjs |
---|---|---|---|---|---|
Keccak256 | 142.1 ms (~1x) | 75.4 ms (~2x) | 287.7 ms (slower) | 140 ms (~1x) | 147.1 ms |
SHA256 | 41 ms (~2x) | 51.3 ms (~1.7x) | 171.3 ms (slower) | 93.9 ms (~1x) | 91.8 ms |
RSA | 153 ms (~19x) | - | 2937.5 ms (~1x) | 2312.3 ms (~1.2x) | 2979.5 ms |
Semaphore-32 | 22 ms (~3.5x) | 14.6 ms (~5.3x) | 266.5 ms (slower) | 38.9 ms (~2x) | 77.6 ms |
Anon Aadhaar | 285.1 ms | - | 3284.7 ms | 1490.8 ms | - |
Proof generation | rapidsnark | ark-works | snarkjs |
---|---|---|---|
Keccak256 | 630.3 ms (~8.2x) | 956.9 ms (~5.4x) | 5182.1 ms |
SHA256 | 186.7 ms (~8.2x) | 498.6 ms (~3x) | 1487 ms |
RSA | 749.1 ms (~8.8x) | 2250.8 ms (~3x) | 6604.5 ms |
Semaphore-32 | 143.3 ms (~6.9x) | 151.4 ms (~6.6x) | 1001.6 ms |
Anon Aadhaar | 3131.7 ms | 10681.6 ms | - |
Android
Benchmarks on an Samsung S23 Ultra (2023).
Witness generation | witnesscalc | circom-witnesscalc | wasmer | w2c | snarkjs |
---|---|---|---|---|---|
Keccak256 | 101.4 ms (~3x) | 71 ms (~4x) | 507.3 ms (slower) | 210.5 ms (~1.3x) | 292.3 ms |
SHA256 | 29 ms (~5x) | 44 ms (~3.5x) | 271.6 ms (slower) | 106.9 ms (~1.4x) | 157.9 ms |
RSA | 155 ms (~25x) | - | 4723 ms (slower) | 3751 ms (~1x) | 3958 ms |
Semaphore-32 | 10.3 ms (~7x) | 14.7 ms (~5x) | 416.9 ms (slower) | 32.8 ms (~2x) | 74.1 ms |
Anon Aadhaar | 365.1 ms (~8.7x) | - | 5359.6 ms (slower) | 2716.4 ms (~1.1x) | 3207.5 ms |
Proof generation | rapidsnark | ark-works | snarkjs |
---|---|---|---|
Keccak256 | 743.7 ms (~14x) | 2330.4 ms (~4.7x) | 11096.4 ms |
SHA256 | 228.4 ms (~15x) | 1575.2 ms (~2x) | 3514.8 ms |
RSA | 950 ms (~14x) | 5839 ms (~2.3x) | 13442 ms |
Semaphore-32 | 165.8 ms (~13x) | 276.9 ms (~7.7x) | 2146 ms |
Anon Aadhaar | 3394.5 ms (~15x) | 33239.2 ms (~1.5x) | 51546.3 ms |
macOS
Benchmarks on an Macbook Pro M1 Max (2021).
Witness generation | witnesscalc | circom-witnesscalc | wasmer | w2c | snarkjs |
---|---|---|---|---|---|
Keccak256 | 63.9 ms (~5x) | 69.6 ms (~5x) | 507.7 ms (slower) | 214.6 ms (~1.6x) | 348.7 ms |
SHA256 | 22 ms (~10x) | 32 ms (~7x) | 272 ms (slower) | 112 ms (~2x) | 225 ms |
RSA | 164 ms (~29x) | - | 5326 ms (slower) | 4796 ms (slower) | 4777 ms |
Semaphore-32 | 7.1 ms (~18x) | 5 ms (~26x) | 287 ms (slower) | 34.9 ms (~3.7x) | 130 ms |
Anon Aadhaar | 324 ms (~10x) | - | 5369 ms (slower) | 2902 ms (~1.2x) | 3437 ms |
Proof generation | rapidsnark | ark-works | snarkjs |
---|---|---|---|
Keccak256 | 528 ms (~7x) | 1161 ms (~3.3x) | 3873 ms |
SHA256 | 158 ms (~9x) | 779 ms (~2x) | 1462 ms |
RSA | 676 ms (~8x) | 3005 ms (~1.8x) | 5553 ms |
Semaphore-32 | 112 ms (~7.8x) | 84 ms (~10x) | 877 ms |
Anon Aadhaar | 2421 ms (~8x) | 14142 ms (~1.3x) | 19794 ms |
Web
We have enabled wasm-bindgen-rayon
for multithreading in the browser. Below is a benchmark comparing arkworks with wasm-bindgen-rayon
against snarkjs
.
-
iPhone 16 Pro
Proof generation ark-works with rayon
snarkjs Keccak256 1717.81 ms (~3x) 5166.02 ms SHA256 601.32 ms 380.61 ms (~1.5x) RSA 7152.85 ms (~1.1x) 8473.58 ms Semaphore-32 652.07 ms (~1.4x) 919.54 ms Anon Aadhaar - ms - ms -
Android Samsung S23U
Proof generation ark-works with rayon
snarkjs Keccak256 2733.15 ms (~2.7x) 7412.39 ms SHA256 980.64 ms (~2.4x) 2379.58 ms RSA 9313.07 ms (~1.1x) 10725.49 ms Semaphore-32 792.87 ms (~1.3x) 1045.34 ms Anon Aadhaar - ms - ms
Details: zkmopro/mopro#290
Halo2
In summary:
The performance of the Mopro build is comparable to that of native Halo2 build.
The below tests were run on a Macbook Pro M1 Pro (2021) as well as an iPhone 15 Pro (2023).
Keccak256 | Prove Time (s) | Verify Time (s) |
---|---|---|
Native (M1 Pro) | 10.3 s | 0.15 s |
iPhone 15 Pro | 11.0 s | 0.12 s |
Pixel 6 Pro | 23.9 s | 0.51 s |
Web | 26.6 s | 0.55 s |
RSA | Prove Time (s) | Verify Time (s) |
---|---|---|
Native (M1 Pro) | 26.9 s | 4.0 s |
iPhone 15 Pro | crashes | crashes |
Pixel 6 Pro | crashes | crashes |
Web | Not Support | x |
Note that the iPhone 15 Pro and Pixel 6 Pro crash when running the RSA circuit due to the large memory requirements. The circuit needs around 5GB of memory to run, while the iPhone 15 Pro and Pixel 6 Pro usually limits the application memory usage to 3GB. Note that the RSA circuit is built on top of former version of Halo2. When it generates a proof on web, it crashes inside Halo2 module.
Noir
We target nargo v1.0.0-beta.3
and bb v0.82.2
, ensuring all related dependencies are aligned (e.g., @noir-lang/noir_js@1.0.0-beta.3, @aztec/bb.js@0.82.2). The benchmarks below were run on a MacBook Air M3 (2024) and a Pixel 6 (2021). We report the fastest result from multiple runs to reduce cold-start effects.
On iOS, the benchmark runs using the "My Mac (Designed for iPad)" target. On Android, it runs on a Pixel 6 in release mode. On bb CLI, we measure wall-clock time with the time bb prove
command. On the website, the benchmark runs in a browser-based (WASM) environment.
Circuit | iOS | Android | bb CLI (Laptop) | Web (Laptop) |
---|---|---|---|---|
Keccak256 | 349 ms (~11.8×) | 1303 ms (~3.2×) | 345 ms (~12.0×) | 4122 ms |
RSA | 312 ms (~6.6×) | 1091 ms (~1.9×) | 221 ms (~9.4×) | 2068 ms |
zkemail | 1309 ms (~5.0×) | 4757 ms (~1.4×) | 804 ms (~8.2×) | 6590 ms |
anon aadhaar | 2225 ms (~7.7×) | 8179 ms (~2.1×) | 1366 ms (~12.5×) | 17030 ms |
semaphore | 828 ms (~5.6×) | 3990 ms (~1.2×) | 436 ms (~10.6×) | 4638 ms |
Benchmark circuit details:
- Keccak256: From Noir Stdlib.
- RSA: pkcs1v15 signature verification (SHA-256). (see details in zkpassport/noir_rsa)
- zkEmail: Header extraction circuit (
Mach-34/zkemail.nr_header_demo
). - Anon Aadhaar: Updated circuit (nargo v1.0.0-beta.3) in
anon-aadhaar/anon-aadhaar-noir#6
. - Semaphore: From
hashcloak/semaphore-noir
.
Details: zkmopro/mopro#414