Skip to content

Perf: Improve compiler speed - #427

Open
anudit wants to merge 1 commit into
iden3:masterfrom
anudit:master
Open

Perf: Improve compiler speed#427
anudit wants to merge 1 commit into
iden3:masterfrom
anudit:master

Conversation

@anudit

@anudit anudit commented Aug 25, 2026

Copy link
Copy Markdown

While testing our circuits we found some performance improvements.
This speeds up compilation ~2x across the board.

Changes

# Change Where Gain
1 execute_component deep-cloned the whole ComponentRepresentation (hashmap of memory slices, each cloning AssignmentState + AST Meta) on every signal access into a subcomponent. Now access_values_by_reference - read-only there anyway, same bounds checks and errors. This clone is what the 2.1.9→2.2.x component/bus rework introduced. constraint_generation/src/execute.rs keccak256 24→13 s
2 FxHash instead of SipHash on the simplification/constraint maps, they're keyed by signal ids and compiler-controlled strings, so DoS resistance buys nothing and cost ~13 % of simplification. No new dependency. write_constraint_usize and apply_correspondence are now generic over the hasher. circom_algebra/src/fast_hash.rs (new); circom_algebra, constraint_list, dag jwt1024 19.1→16.5 s
3 mimalloc as global allocator. The profile's ~20 % allocator self-time was the system allocator being slow circom/src/main.rs jwt1024 16.5→12.2 s
4 modulus(a,b) computed ((a % b) + b) % b; since a % b is already in (-b, b) for positive b, the second division was always a no-op. circom_algebra/src/modular_arithmetic.rs jwt1024 12.2→10.6 s
5 lto = "thin", codegen-units = 1, panic = "abort" - the workspace had no [profile.release] at all. Cargo.toml ~5 %

Bug fixes

Two circom_algebra tests already failed on unmodified a100fae;

  • complement didn't reduce its operand. It truncates to the field's bit width before flipping, so an operand >= field lost its high bits and ~~x != x mod p. Now reduces into [0, field) first, like every other op in the module.
  • algebra_constraint_apply_substitution skipped a step. apply_substitution deliberately leaves the raw form (explicit constant coefficients, zero or not); its internal fix_constraint is commented out because the pipeline calls it afterwards. The test now does the same.

Benchmarks on some of our circuits

Apple M2 Max (12 cores, 64 GB, macOS arm64). hyperfine with warmup, heavy circuits
×3 runs, light ×10. Flags: --r1cs --wasm --c -l ./node_modules. All three binaries
measured identically.

Circuit Constraints v2.2.3 after v2.2.3 before v2.1.9 Improvement
keccak256 239,211 6.00 s 18.76 s 9.77 s 3.13×
jwt1024 685,509 7.87 s 15.63 s 16.61 s 1.99×
oauth512 683,083 7.35 s 14.05 s 14.91 s 1.91×
jwt512 420,292 4.48 s 8.86 s 10.21 s 1.98×
jwt256 287,555 2.92 s 5.83 s 6.70 s 2.00×
aadhaar 164,841 1.40 s 2.86 s 4.07 s 2.04×
rsa 153,137 0.99 s 1.95 s 2.84 s 1.98×
sha256 31,699 0.72 s 1.37 s 1.42 s 1.92×
semaphore20 15,875 0.49 s 0.78 s 1.14 s 1.58×
loginProof 5,244 0.57 s 0.85 s 1.11 s 1.49×
merkle 10,464 0.42 s 0.64 s 0.79 s 1.52×

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant