From 6000df9779911a241423b0ff4c6576765fdc4267 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Mon, 7 Jan 2019 09:38:19 -0700 Subject: [PATCH] Optimize has_duplicates() for short slices --- benches/runtime.rs | 14 ++++++++++++++ src/runtime.rs | 15 ++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 benches/runtime.rs diff --git a/benches/runtime.rs b/benches/runtime.rs new file mode 100644 index 0000000000..ecaf4176b8 --- /dev/null +++ b/benches/runtime.rs @@ -0,0 +1,14 @@ +#![feature(test)] + +extern crate test; + +use solana::runtime::*; +use test::Bencher; + +#[bench] +fn bench_has_duplicates(bencher: &mut Bencher) { + bencher.iter(|| { + let data = test::black_box([1, 2, 3]); + assert!(!has_duplicates(&data)); + }) +} diff --git a/src/runtime.rs b/src/runtime.rs index 71b145fd14..2eb63d060d 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -5,8 +5,6 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::system_program; use solana_sdk::transaction::Transaction; use solana_system_program; -use std::collections::HashSet; -use std::iter::FromIterator; /// Reasons the runtime might have rejected a transaction. #[derive(Debug, PartialEq, Eq, Clone)] @@ -118,9 +116,16 @@ fn execute_instruction( } /// Return true if the slice has any duplicate elements -fn has_duplicates(xs: &[T]) -> bool { - let xs_set: HashSet<&T> = HashSet::from_iter(xs.iter()); - xs.len() != xs_set.len() +pub fn has_duplicates(xs: &[T]) -> bool { + // Note: This is an O(n^2) algorithm, but requires no heap allocations. The benchmark + // `bench_has_duplicates` in benches/runtime.rs shows that this implementation is + // ~50 times faster than using HashSet for very short slices. + for i in 1..xs.len() { + if xs[i..].contains(&xs[i - 1]) { + return true; + } + } + false } /// Get mut references to a subset of elements.