Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Perf] Use SmallVec for additional temporary allocations #4

Open
wants to merge 7 commits into
base: mainnet-staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion console/account/src/compute_key/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for ComputeKey<N> {
/// Returns the little-endian bits of the compute key.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
// Write the `pk_sig` bits.
self.pk_sig.write_bits_le(vec);
// Write the `pr_sig` bits.
Expand Down
4 changes: 2 additions & 2 deletions console/account/src/signature/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ impl<N: Network> Signature<N> {

// Construct the hash input as (r * G, pk_sig, pr_sig, address, message).
let mut preimage = Vec::with_capacity(4 + message.len());
preimage.extend([g_r, pk_sig, pr_sig, *address].map(|point| point.to_x_coordinate()));
preimage.extend(message);
Extend::extend(&mut preimage, [g_r, pk_sig, pr_sig, *address].map(|point| point.to_x_coordinate()));
Extend::extend(&mut preimage, message);

// Compute the verifier challenge.
let challenge = N::hash_to_scalar_psd8(&preimage)?;
Expand Down
2 changes: 1 addition & 1 deletion console/account/src/signature/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Signature<N> {
/// Returns the little-endian bits of the signature.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
// Write the challenge bits.
self.challenge.write_bits_le(vec);
// Write the response bits.
Expand Down
4 changes: 2 additions & 2 deletions console/account/src/signature/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ impl<N: Network> Signature<N> {

// Construct the hash input as (r * G, pk_sig, pr_sig, address, message).
let mut preimage = Vec::with_capacity(4 + message.len());
preimage.extend([g_r, pk_sig, pr_sig, **address].map(|point| point.to_x_coordinate()));
preimage.extend(message);
Extend::extend(&mut preimage, [g_r, pk_sig, pr_sig, **address].map(|point| point.to_x_coordinate()));
Extend::extend(&mut preimage, message);

// Hash to derive the verifier challenge, and return `false` if this operation fails.
let candidate_challenge = match N::hash_to_scalar_psd8(&preimage) {
Expand Down
10 changes: 6 additions & 4 deletions console/algorithms/src/bhp/hash_uncompressed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

use super::*;

use smallvec::SmallVec;

impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> HashUncompressed
for BHP<E, NUM_WINDOWS, WINDOW_SIZE>
{
Expand All @@ -39,7 +41,7 @@ impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> HashUncompres
let mut digest = Group::<E>::zero();

// Prepare a reusable vector for the preimage.
let mut preimage = Vec::with_capacity(num_hasher_bits);
let mut preimage: SmallVec<[bool; 2048]> = SmallVec::new();

// Compute the hash of the input.
for (i, input_bits) in input.chunks(max_input_bits_per_iteration).enumerate() {
Expand All @@ -48,16 +50,16 @@ impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> HashUncompres
// Construct the first iteration as: [ 0...0 || DOMAIN || LENGTH(INPUT) || INPUT[0..BLOCK_SIZE] ].
true => {
// Initialize a vector for the hash preimage.
preimage.extend(&self.domain);
VecLike::extend_from_slice(&mut preimage, &self.domain);
(input.len() as u64).write_bits_le(&mut preimage);
preimage.extend(input_bits);
VecLike::extend_from_slice(&mut preimage, input_bits);
}
// Construct the subsequent iterations as: [ PREVIOUS_HASH[0..DATA_BITS] || INPUT[I * BLOCK_SIZE..(I + 1) * BLOCK_SIZE] ].
false => {
// Initialize a vector for the hash preimage.
digest.to_x_coordinate().write_bits_le(&mut preimage);
preimage.truncate(num_data_bits);
preimage.extend(input_bits);
VecLike::extend_from_slice(&mut preimage, input_bits);
}
}
// Hash the preimage for this iteration.
Expand Down
5 changes: 5 additions & 0 deletions console/collections/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ default-features = false
[dependencies.rayon]
version = "1"

[dependencies.smallvec]
version = "1.11"
features = ["const_new"]
default_features = false

[dev-dependencies.snarkvm-console-network]
path = "../network"

Expand Down
4 changes: 2 additions & 2 deletions console/collections/src/kary_merkle_tree/helpers/leaf_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> LeafHash for
let mut input = Vec::with_capacity(1 + leaf.len());
// Prepend the leaf with a `false` bit.
input.push(false);
input.extend(leaf);
Vec::extend_from_slice(&mut input, leaf);
// Hash the input.
Hash::hash(self, &input)
}
Expand Down Expand Up @@ -76,7 +76,7 @@ impl<const TYPE: u8, const VARIANT: usize> LeafHash for Keccak<TYPE, VARIANT> {
let mut input = Vec::with_capacity(1 + leaf.len());
// Prepend the leaf with a `false` bit.
input.push(false);
input.extend(leaf);
Vec::extend_from_slice(&mut input, leaf);
// Hash the input.
let output = Hash::hash(self, &input)?;
// Read the first VARIANT bits.
Expand Down
2 changes: 1 addition & 1 deletion console/collections/src/merkle_tree/helpers/leaf_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> LeafHash for
let mut input = Vec::with_capacity(1 + leaf.len());
// Prepend the leaf with a `false` bit.
input.push(false);
input.extend(leaf);
Vec::extend_from_slice(&mut input, leaf);
// Hash the input.
Hash::hash(self, &input)
}
Expand Down
3 changes: 2 additions & 1 deletion console/collections/src/merkle_tree/helpers/path_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use snarkvm_console_types::prelude::*;

#[cfg(not(feature = "serial"))]
use rayon::prelude::*;
use smallvec::SmallVec;

/// A trait for a Merkle path hash function.
pub trait PathHash: Clone + Send + Sync {
Expand Down Expand Up @@ -45,7 +46,7 @@ impl<E: Environment, const NUM_WINDOWS: u8, const WINDOW_SIZE: u8> PathHash for

/// Returns the hash of the given child nodes.
fn hash_children(&self, left: &Self::Hash, right: &Self::Hash) -> Result<Self::Hash> {
let mut input = Vec::with_capacity(1 + <Self::Hash as SizeInBits>::size_in_bits() * 2);
let mut input: SmallVec<[bool; 512]> = SmallVec::new();
// Prepend the nodes with a `true` bit.
input.push(true);
left.write_bits_le(&mut input);
Expand Down
2 changes: 1 addition & 1 deletion console/collections/src/merkle_tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ impl<E: Environment, LH: LeafHash<Hash = PH::Hash>, PH: PathHash<Hash = Field<E>
// Initialize the Merkle tree.
let mut tree = Vec::with_capacity(self.tree.len());
// Extend the new Merkle tree with the existing leaf hashes.
tree.extend(&self.tree);
Extend::extend(&mut tree, &self.tree);

// Update the rest of the tree with the new path hashes.
let mut index = Some(start + leaf_index);
Expand Down
1 change: 1 addition & 0 deletions console/network/environment/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub mod prelude {
ToBytes,
ToBytesSerializer,
Uniform,
VecLike,
};

pub use core::{
Expand Down
5 changes: 5 additions & 0 deletions console/program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,10 @@ version = "1.0"
version = "1.0"
features = [ "preserve_order" ]

[dependencies.smallvec]
version = "1.11"
features = [ "const_new" ]
default-features = false

[dev-dependencies.bincode]
version = "1.3"
2 changes: 1 addition & 1 deletion console/program/src/data/ciphertext/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Ciphertext<N> {
/// Returns this ciphertext as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
let initial_len = vec.len();
self.0.write_bits_le(vec);
assert_eq!(self.0.len() * Field::<N>::size_in_bits(), vec.len() - initial_len);
Expand Down
2 changes: 1 addition & 1 deletion console/program/src/data/future/argument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl<N: Network> ToBytes for Argument<N> {
impl<N: Network> ToBits for Argument<N> {
/// Returns the argument as a list of **little-endian** bits.
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Self::Plaintext(plaintext) => {
vec.push(false);
Expand Down
2 changes: 1 addition & 1 deletion console/program/src/data/future/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::*;
impl<N: Network> ToBits for Future<N> {
/// Returns the future as a list of **little-endian** bits.
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
// Write the bits for the program ID.
let program_id_bits = self.program_id.to_bits_le();
u16::try_from(program_id_bits.len()).or_halt_with::<N>("Program ID exceeds u16::MAX bits").write_bits_le(vec);
Expand Down
7 changes: 6 additions & 1 deletion console/program/src/data/identifier/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

use super::*;

use smallvec::SmallVec;

impl<N: Network> Parser for Identifier<N> {
/// Parses a string into an identifier.
///
Expand Down Expand Up @@ -60,8 +62,11 @@ impl<N: Network> FromStr for Identifier<N> {

// Note: The string bytes themselves are **not** little-endian. Rather, they are order-preserving
// for reconstructing the string when recovering the field element back into bytes.
let mut field_bits: SmallVec<[bool; 128]> = SmallVec::new();
identifier.as_bytes().write_bits_le(&mut field_bits);

Ok(Self(
Field::<N>::from_bits_le(&identifier.as_bytes().to_bits_le())?,
Field::<N>::from_bits_le(&field_bits)?,
u8::try_from(identifier.len()).or_halt_with::<N>("Identifier `from_str` exceeds maximum length"),
))
}
Expand Down
4 changes: 2 additions & 2 deletions console/program/src/data/identifier/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Identifier<N> {
/// Returns the little-endian bits of the identifier.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
(&self).write_bits_le(vec);
}

Expand All @@ -28,7 +28,7 @@ impl<N: Network> ToBits for Identifier<N> {

impl<N: Network> ToBits for &Identifier<N> {
/// Returns the little-endian bits of the identifier.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
let initial_len = vec.len();
self.0.write_bits_le(vec);
vec.truncate(initial_len + 8 * self.1 as usize);
Expand Down
4 changes: 2 additions & 2 deletions console/program/src/data/literal/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Literal<N> {
/// Returns the little-endian bits of the literal.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
(&self).write_bits_le(vec);
}

Expand All @@ -28,7 +28,7 @@ impl<N: Network> ToBits for Literal<N> {

impl<N: Network> ToBits for &Literal<N> {
/// Returns the little-endian bits of the literal.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Literal::Address(literal) => literal.write_bits_le(vec),
Literal::Boolean(literal) => literal.write_bits_le(vec),
Expand Down
6 changes: 3 additions & 3 deletions console/program/src/data/plaintext/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Plaintext<N> {
/// Returns this plaintext as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Self::Literal(literal, bits_le) => {
// Compute the bits.
Expand Down Expand Up @@ -78,7 +78,7 @@ impl<N: Network> ToBits for Plaintext<N> {
.write_bits_le(&mut bits_le);

// Write the element.
bits_le.extend(element_bits);
VecLike::extend(&mut bits_le, element_bits);
}
bits_le
});
Expand Down Expand Up @@ -152,7 +152,7 @@ impl<N: Network> ToBits for Plaintext<N> {
.write_bits_be(&mut bits_be);

// Write the element.
bits_be.extend(element_bits);
VecLike::extend(&mut bits_be, element_bits);
}
bits_be
});
Expand Down
4 changes: 2 additions & 2 deletions console/program/src/data/record/entry/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Entry<N, Plaintext<N>> {
/// Returns this entry as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Self::Constant(..) => vec.extend_from_slice(&[false, false]),
Self::Public(..) => vec.extend_from_slice(&[false, true]),
Expand Down Expand Up @@ -46,7 +46,7 @@ impl<N: Network> ToBits for Entry<N, Plaintext<N>> {

impl<N: Network> ToBits for Entry<N, Ciphertext<N>> {
/// Returns this entry as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Self::Constant(..) => vec.extend_from_slice(&[false, false]),
Self::Public(..) => vec.extend_from_slice(&[false, true]),
Expand Down
4 changes: 2 additions & 2 deletions console/program/src/data/record/helpers/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl<N: Network> Owner<N, Ciphertext<N>> {

impl<N: Network> ToBits for Owner<N, Plaintext<N>> {
/// Returns `self` as a boolean vector in little-endian order.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_le(vec),
Expand All @@ -162,7 +162,7 @@ impl<N: Network> ToBits for Owner<N, Plaintext<N>> {

impl<N: Network> ToBits for Owner<N, Ciphertext<N>> {
/// Returns `self` as a boolean vector in little-endian order.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_le(vec),
Expand Down
4 changes: 2 additions & 2 deletions console/program/src/data/record/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::*;

impl<N: Network> ToBits for Record<N, Plaintext<N>> {
/// Returns this data as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
// Compute the data bits.
let mut data_bits_le = vec![];
for (identifier, entry) in &self.data {
Expand Down Expand Up @@ -50,7 +50,7 @@ impl<N: Network> ToBits for Record<N, Plaintext<N>> {

impl<N: Network> ToBits for Record<N, Ciphertext<N>> {
/// Returns this data as a list of **little-endian** bits.
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
// Compute the data bits.
let mut data_bits_le = vec![];
for (identifier, entry) in &self.data {
Expand Down
2 changes: 1 addition & 1 deletion console/program/src/data/value/to_bits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::*;
impl<N: Network> ToBits for Value<N> {
/// Returns the stack value as a list of **little-endian** bits.
#[inline]
fn write_bits_le(&self, vec: &mut Vec<bool>) {
fn write_bits_le<T: VecLike>(&self, vec: &mut T) {
match self {
Self::Plaintext(plaintext) => plaintext.write_bits_le(vec),
Self::Record(record) => record.write_bits_le(vec),
Expand Down
25 changes: 14 additions & 11 deletions console/program/src/function_id/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,25 @@ use snarkvm_console_algorithms::Result;
use snarkvm_console_network::Network;
use snarkvm_console_types::{Field, U16, U8};

use smallvec::SmallVec;

/// Compute the function ID as `Hash(network_id, program_id.len(), program_id, function_name.len(), function_name)`.
pub fn compute_function_id<N: Network>(
network_id: &U16<N>,
program_id: &ProgramID<N>,
function_name: &Identifier<N>,
) -> Result<Field<N>> {
N::hash_bhp1024(
&(
*network_id,
U8::<N>::new(program_id.name().size_in_bits()),
program_id.name(),
U8::<N>::new(program_id.network().size_in_bits()),
program_id.network(),
U8::<N>::new(function_name.size_in_bits()),
function_name,
)
.to_bits_le(),
let mut preimage: SmallVec<[bool; 256]> = SmallVec::new();
(
*network_id,
U8::<N>::new(program_id.name().size_in_bits()),
program_id.name(),
U8::<N>::new(program_id.network().size_in_bits()),
program_id.network(),
U8::<N>::new(function_name.size_in_bits()),
function_name,
)
.write_bits_le(&mut preimage);

N::hash_bhp1024(&preimage)
}
Loading