Skip to content

Commit

Permalink
feat: Avoid heap allocs when going to/from field (#7547)
Browse files Browse the repository at this point in the history
This PR plus [integer operations using
u128](#7518) makes
[this
test](https://github.com/zac-williamson/noir_bigcurve/blob/main/src/bigcurve_test.nr#L129)
go from 110 seconds of ACVM execution to around 22 seconds (34 seconds
with only the change of the integer ops)

Flamegraph before:

![image](https://github.com/user-attachments/assets/5281fc59-9172-4a5d-97cd-1aa98d25bd41)

Flamegraph after:

![image](https://github.com/user-attachments/assets/745b8bb8-4c26-4123-919b-f10c99e9dd7c)

---------

Co-authored-by: Maxim Vezenov <[email protected]>
  • Loading branch information
sirasistant and vezenovm authored Jul 23, 2024
1 parent e515b71 commit 086522d
Showing 1 changed file with 24 additions and 8 deletions.
32 changes: 24 additions & 8 deletions noir/noir-repo/acvm-repo/acir_field/src/field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,17 +139,25 @@ impl<'de, T: ark_ff::PrimeField> Deserialize<'de> for FieldElement<T> {

impl<F: PrimeField> From<u128> for FieldElement<F> {
fn from(a: u128) -> FieldElement<F> {
let result = match F::from_str(&a.to_string()) {
Ok(result) => result,
Err(_) => panic!("Cannot convert u128 as a string to a field element"),
};
FieldElement(result)
FieldElement(F::from(a))
}
}

impl<F: PrimeField> From<usize> for FieldElement<F> {
fn from(a: usize) -> FieldElement<F> {
FieldElement::from(a as u128)
FieldElement::from(a as u64)
}
}

impl<F: PrimeField> From<u64> for FieldElement<F> {
fn from(a: u64) -> FieldElement<F> {
FieldElement(F::from(a))
}
}

impl<F: PrimeField> From<u32> for FieldElement<F> {
fn from(a: u32) -> FieldElement<F> {
FieldElement(F::from(a))
}
}

Expand Down Expand Up @@ -265,8 +273,16 @@ impl<F: PrimeField> AcirField for FieldElement<F> {
}

fn to_u128(self) -> u128 {
let bytes = self.to_be_bytes();
u128::from_be_bytes(bytes[16..32].try_into().unwrap())
let as_bigint = self.0.into_bigint();
let limbs = as_bigint.as_ref();

let mut result = limbs[0] as u128;
if limbs.len() > 1 {
let high_limb = limbs[1] as u128;
result += high_limb << 64;
}

result
}

fn try_into_u128(self) -> Option<u128> {
Expand Down

0 comments on commit 086522d

Please sign in to comment.