perf: reduce format!-related allocations and move them to closures where possible

Signed-off-by: ljedrz <ljedrz@gmail.com>
This commit is contained in:
ljedrz 2020-10-22 14:26:11 +02:00
parent 63f80c0472
commit 4ccc9c31db
14 changed files with 121 additions and 127 deletions

View File

@ -65,15 +65,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
let (outer_scope, function_call) = function_value.extract_function(file_scope, &span)?;
let name_unique = format!(
"function call {} {}:{}",
function_call.get_name(),
span.line,
span.start,
);
let name_unique = || {
format!(
"function call {} {}:{}",
function_call.get_name(),
span.line,
span.start,
)
};
self.enforce_function(
&mut cs.ns(|| name_unique),
&mut cs.ns(name_unique),
&outer_scope,
function_scope,
function_call,

View File

@ -33,9 +33,12 @@ pub fn enforce_and<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<
let name = format!("{} && {}", left, right);
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
let name_unique = format!("{} {}:{}", name, span.line, span.start);
let result = Boolean::and(cs.ns(|| name_unique), &left_bool, &right_bool)
.map_err(|e| BooleanError::cannot_enforce("&&".to_string(), e, span.to_owned()))?;
let result = Boolean::and(
cs.ns(|| format!("{} {}:{}", name, span.line, span.start)),
&left_bool,
&right_bool,
)
.map_err(|e| BooleanError::cannot_enforce("&&".to_string(), e, span.to_owned()))?;
return Ok(ConstrainedValue::Boolean(result));
}

View File

@ -33,9 +33,12 @@ pub fn enforce_or<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F
let name = format!("{} || {}", left, right);
if let (ConstrainedValue::Boolean(left_bool), ConstrainedValue::Boolean(right_bool)) = (left, right) {
let name_unique = format!("{} {}:{}", name, span.line, span.start);
let result = Boolean::or(cs.ns(|| name_unique), &left_bool, &right_bool)
.map_err(|e| BooleanError::cannot_enforce("||".to_string(), e, span.to_owned()))?;
let result = Boolean::or(
cs.ns(|| format!("{} {}:{}", name, span.line, span.start)),
&left_bool,
&right_bool,
)
.map_err(|e| BooleanError::cannot_enforce("||".to_string(), e, span.to_owned()))?;
return Ok(ConstrainedValue::Boolean(result));
}

View File

@ -61,12 +61,13 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
let condition = indicator.unwrap_or(Boolean::Constant(true));
let name_unique = format!("select {} {}:{}", result, span.line, span.start);
let selected_value =
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &result, return_value)
.map_err(|_| {
StatementError::select_fail(result.to_string(), return_value.to_string(), span.to_owned())
})?;
let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| format!("select {} {}:{}", result, span.line, span.start)),
&condition,
&result,
return_value,
)
.map_err(|_| StatementError::select_fail(result.to_string(), return_value.to_string(), span.to_owned()))?;
*return_value = selected_value;
}

View File

@ -52,9 +52,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ConstrainedValue::Array(old) => {
new_value.resolve_type(Some(old[index].to_type(&span)?), &span)?;
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| name_unique),
cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)),
&condition,
&new_value,
&old[index],
@ -89,12 +88,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
_ => return Err(StatementError::array_assign_range(span.to_owned())),
};
let name_unique = format!("select {} {}:{}", new_array, span.line, span.start);
let selected_array =
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_array, old_array)
.map_err(|_| {
StatementError::select_fail(new_array.to_string(), old_array.to_string(), span.to_owned())
})?;
let selected_array = ConstrainedValue::conditionally_select(
cs.ns(|| format!("select {} {}:{}", new_array, span.line, span.start)),
&condition,
&new_array,
old_array,
)
.map_err(|_| {
StatementError::select_fail(new_array.to_string(), old_array.to_string(), span.to_owned())
})?;
*old_array = selected_array;
}

View File

@ -61,12 +61,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
new_value.resolve_type(Some(old_value.to_type(&span)?), &span)?;
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let selected_value =
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, old_value)
.map_err(|_| {
StatementError::select_fail(new_value.to_string(), old_value.to_string(), span.to_owned())
})?;
let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)),
&condition,
&new_value,
old_value,
)
.map_err(|_| {
StatementError::select_fail(new_value.to_string(), old_value.to_string(), span.to_owned())
})?;
*old_value = selected_value;

View File

@ -68,9 +68,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
new_value.resolve_type(Some(value.to_type(span)?), span)?;
// Conditionally select the value if this branch is executed.
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let mut selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| name_unique),
cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)),
&condition,
&new_value,
&member.1,

View File

@ -44,12 +44,15 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ConstrainedValue::Tuple(old) => {
new_value.resolve_type(Some(old[index].to_type(&span)?), &span)?;
let name_unique = format!("select {} {}:{}", new_value, span.line, span.start);
let selected_value =
ConstrainedValue::conditionally_select(cs.ns(|| name_unique), &condition, &new_value, &old[index])
.map_err(|_| {
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span.to_owned())
})?;
let selected_value = ConstrainedValue::conditionally_select(
cs.ns(|| format!("select {} {}:{}", new_value, span.line, span.start)),
&condition,
&new_value,
&old[index],
)
.map_err(|_| {
StatementError::select_fail(new_value.to_string(), old[index].to_string(), span.to_owned())
})?;
old[index] = selected_value;
}

View File

@ -67,9 +67,8 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
);
// Evaluate statements and possibly return early
let name_unique = format!("for loop iteration {} {}:{}", i, span.line, span.start);
let mut result = self.evaluate_branch(
&mut cs.ns(|| name_unique),
&mut cs.ns(|| format!("for loop iteration {} {}:{}", i, span.line, span.start)),
file_scope,
function_scope,
indicator,

View File

@ -81,12 +81,10 @@ impl Address {
None => None,
};
let address_name = format!("{}: address", name);
let address_namespace = format!("`{}` {}:{}", address_name, span.line, span.start);
let address = Address::alloc(cs.ns(|| address_namespace), || {
address_value.ok_or(SynthesisError::AssignmentMissing)
})
let address = Address::alloc(
cs.ns(|| format!("`{}: address` {}:{}", name, span.line, span.start)),
|| address_value.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| AddressError::missing_address(span.to_owned()))?;
Ok(ConstrainedValue::Address(address))

View File

@ -42,13 +42,11 @@ pub(crate) fn allocate_bool<F: Field + PrimeField, CS: ConstraintSystem<F>>(
option: Option<bool>,
span: &Span,
) -> Result<Boolean, BooleanError> {
let boolean_name = format!("{}: bool", name);
let boolean_name_unique = format!("`{}` {}:{}", boolean_name, span.line, span.start);
Boolean::alloc(cs.ns(|| boolean_name_unique), || {
option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| BooleanError::missing_boolean(boolean_name.to_owned(), span.to_owned()))
Boolean::alloc(
cs.ns(|| format!("`{}: bool` {}:{}", name, span.line, span.start)),
|| option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| BooleanError::missing_boolean(format!("{}: bool", name), span.to_owned()))
}
pub(crate) fn bool_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(

View File

@ -31,13 +31,11 @@ pub(crate) fn allocate_field<F: Field + PrimeField, CS: ConstraintSystem<F>>(
option: Option<String>,
span: &Span,
) -> Result<FieldType<F>, FieldError> {
let field_name = format!("{}: field", name);
let field_name_unique = format!("`{}` {}:{}", field_name, span.line, span.start);
FieldType::alloc(cs.ns(|| field_name_unique), || {
option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| FieldError::missing_field(field_name, span.to_owned()))
FieldType::alloc(
cs.ns(|| format!("`{}: field` {}:{}", name, span.line, span.start)),
|| option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| FieldError::missing_field(format!("{}: field", name), span.to_owned()))
}
pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(

View File

@ -31,13 +31,11 @@ pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: Constra
option: Option<GroupValue>,
span: &Span,
) -> Result<G, GroupError> {
let group_name = format!("{}: group", name);
let group_name_unique = format!("`{}` {}:{}", group_name, span.line, span.start);
G::alloc(cs.ns(|| group_name_unique), || {
option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| GroupError::missing_group(group_name, span.to_owned()))
G::alloc(
cs.ns(|| format!("`{}: group` {}:{}", name, span.line, span.start)),
|| option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| GroupError::missing_group(format!("{}: group", name), span.to_owned()))
}
pub(crate) fn group_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(

View File

@ -189,155 +189,142 @@ impl Integer {
) -> Result<Self, IntegerError> {
Ok(match integer_type {
IntegerType::U8 => {
let u8_name = format!("{}: u8", name);
let u8_name_unique = format!("`{}` {}:{}", u8_name, span.line, span.start);
let u8_option = option.map(|s| {
s.parse::<u8>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let u8_result = UInt8::alloc(cs.ns(|| u8_name_unique), || {
let u8_result = UInt8::alloc(cs.ns(|| format!("`{}: u8` {}:{}", name, span.line, span.start)), || {
u8_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(u8_name, span.to_owned()))?;
.map_err(|_| IntegerError::missing_integer(format!("{}: u8", name), span.to_owned()))?;
Integer::U8(u8_result)
}
IntegerType::U16 => {
let u16_name = format!("{}: u16", name);
let u16_name_unique = format!("`{}` {}:{}", u16_name, span.line, span.start);
let u16_option = option.map(|s| {
s.parse::<u16>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let u16_result = UInt16::alloc(cs.ns(|| u16_name_unique), || {
u16_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(u16_name, span.to_owned()))?;
let u16_result = UInt16::alloc(
cs.ns(|| format!("`{}: u16` {}:{}", name, span.line, span.start)),
|| u16_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: u16", name), span.to_owned()))?;
Integer::U16(u16_result)
}
IntegerType::U32 => {
let u32_name = format!("{}: u32", name);
let u32_name_unique = format!("`{}` {}:{}", u32_name, span.line, span.start);
let u32_option = option.map(|s| {
s.parse::<u32>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let u32_result = UInt32::alloc(cs.ns(|| u32_name_unique), || {
u32_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(u32_name, span.to_owned()))?;
let u32_result = UInt32::alloc(
cs.ns(|| format!("`{}: u32` {}:{}", name, span.line, span.start)),
|| u32_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: u32", name), span.to_owned()))?;
Integer::U32(u32_result)
}
IntegerType::U64 => {
let u64_name = format!("{}: u64", name);
let u64_name_unique = format!("`{}` {}:{}", u64_name, span.line, span.start);
let u64_option = option.map(|s| {
s.parse::<u64>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let u64_result = UInt64::alloc(cs.ns(|| u64_name_unique), || {
u64_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(u64_name, span.to_owned()))?;
let u64_result = UInt64::alloc(
cs.ns(|| format!("`{}: u64` {}:{}", name, span.line, span.start)),
|| u64_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: u64", name), span.to_owned()))?;
Integer::U64(u64_result)
}
IntegerType::U128 => {
let u128_name = format!("{}: u128", name);
let u128_name_unique = format!("`{}` {}:{}", u128_name, span.line, span.start);
let u128_option = option.map(|s| {
s.parse::<u128>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let u128_result = UInt128::alloc(cs.ns(|| u128_name_unique), || {
u128_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(u128_name, span.to_owned()))?;
let u128_result = UInt128::alloc(
cs.ns(|| format!("`{}: u128` {}:{}", name, span.line, span.start)),
|| u128_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: u128", name), span.to_owned()))?;
Integer::U128(u128_result)
}
IntegerType::I8 => {
let i8_name = format!("{}: i8", name);
let i8_name_unique = format!("`{}` {}:{}", i8_name, span.line, span.start);
let i8_option = option.map(|s| {
s.parse::<i8>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let i8_result = Int8::alloc(cs.ns(|| i8_name_unique), || {
let i8_result = Int8::alloc(cs.ns(|| format!("`{}: i8` {}:{}", name, span.line, span.start)), || {
i8_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(i8_name, span.to_owned()))?;
.map_err(|_| IntegerError::missing_integer(format!("{}: i8", name), span.to_owned()))?;
Integer::I8(i8_result)
}
IntegerType::I16 => {
let i16_name = format!("{}: i16", name);
let i16_name_unique = format!("`{}` {}:{}", i16_name, span.line, span.start);
let i16_option = option.map(|s| {
s.parse::<i16>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let i16_result = Int16::alloc(cs.ns(|| i16_name_unique), || {
i16_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(i16_name, span.to_owned()))?;
let i16_result = Int16::alloc(
cs.ns(|| format!("`{}: i16` {}:{}", name, span.line, span.start)),
|| i16_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: i16", name), span.to_owned()))?;
Integer::I16(i16_result)
}
IntegerType::I32 => {
let i32_name = format!("{}: i32", name);
let i32_name_unique = format!("`{}` {}:{}", i32_name, span.line, span.start);
let i32_option = option.map(|s| {
s.parse::<i32>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let i32_result = Int32::alloc(cs.ns(|| i32_name_unique), || {
i32_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(i32_name, span.to_owned()))?;
let i32_result = Int32::alloc(
cs.ns(|| format!("`{}: i32` {}:{}", name, span.line, span.start)),
|| i32_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: i32", name), span.to_owned()))?;
Integer::I32(i32_result)
}
IntegerType::I64 => {
let i64_name = format!("{}: i64", name);
let i64_name_unique = format!("`{}` {}:{}", i64_name, span.line, span.start);
let i64_option = option.map(|s| {
s.parse::<i64>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let i64_result = Int64::alloc(cs.ns(|| i64_name_unique), || {
i64_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(i64_name, span.to_owned()))?;
let i64_result = Int64::alloc(
cs.ns(|| format!("`{}: i64` {}:{}", name, span.line, span.start)),
|| i64_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: i64", name), span.to_owned()))?;
Integer::I64(i64_result)
}
IntegerType::I128 => {
let i128_name = format!("{}: i128", name);
let i128_name_unique = format!("`{}` {}:{}", i128_name, span.line, span.start);
let i128_option = option.map(|s| {
s.parse::<i128>()
.map_err(|_| IntegerError::invalid_integer(s, span.to_owned()))
.unwrap()
});
let i128_result = Int128::alloc(cs.ns(|| i128_name_unique), || {
i128_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| IntegerError::missing_integer(i128_name, span.to_owned()))?;
let i128_result = Int128::alloc(
cs.ns(|| format!("`{}: i128` {}:{}", name, span.line, span.start)),
|| i128_option.ok_or(SynthesisError::AssignmentMissing),
)
.map_err(|_| IntegerError::missing_integer(format!("{}: i128", name), span.to_owned()))?;
Integer::I128(i128_result)
}