Skip to content

Commit

Permalink
perf: speed up bytecode_diff_score in debug mode
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Feb 14, 2024
1 parent ba7f576 commit 7e18213
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
28 changes: 27 additions & 1 deletion crates/common/src/contracts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub type ContractsByAddress = BTreeMap<Address, (String, JsonAbi)>;
///
/// Returns a value between `0.0` (identical) and `1.0` (completely different).
pub fn bytecode_diff_score<'a>(mut a: &'a [u8], mut b: &'a [u8]) -> f64 {
// Make sure `a` is the longer one.
if a.len() < b.len() {
std::mem::swap(&mut a, &mut b);
}
Expand All @@ -112,11 +113,36 @@ pub fn bytecode_diff_score<'a>(mut a: &'a [u8], mut b: &'a [u8]) -> f64 {
}

// Count different bytes.
n_different_bytes += std::iter::zip(a, b).filter(|(a, b)| a != b).count();
// SAFETY: `a` is longer than `b`.
n_different_bytes += unsafe { count_different_bytes(a, b) };

n_different_bytes as f64 / a.len() as f64
}

/// Returns the amount of different bytes between two slices.
///
/// # Safety
///
/// `a` must be at least as long as `b`.
unsafe fn count_different_bytes(a: &[u8], b: &[u8]) -> usize {
// This could've been written as `std::iter::zip(a, b).filter(|(x, y)| x != y).count()`,
// however this function is very hot, and has been written to be as primitive as
// possible for lower optimization levels.

let a_ptr = a.as_ptr();
let b_ptr = b.as_ptr();
let len = b.len();

let mut sum = 0;
let mut i = 0;
while i < len {
// SAFETY: `a` is at least as long as `b`, and `i` is in bound of `b`.
sum += unsafe { *a_ptr.add(i) != *b_ptr.add(i) } as usize;
i += 1;
}
sum
}

/// Flattens the contracts into (`id` -> (`JsonAbi`, `Vec<u8>`)) pairs
pub fn flatten_contracts(
contracts: &BTreeMap<ArtifactId, ContractBytecodeSome>,
Expand Down
2 changes: 1 addition & 1 deletion crates/evm/traces/src/identifier/etherscan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl TraceIdentifier for EtherscanIdentifier {
where
A: Iterator<Item = (&'a Address, Option<&'a [u8]>)>,
{
trace!(target: "etherscanidentifier", "identify {:?} addresses", addresses.size_hint().1);
trace!("identify {:?} addresses", addresses.size_hint().1);

let Some(client) = self.client.clone() else {
// no client was configured
Expand Down

0 comments on commit 7e18213

Please sign in to comment.