make next_entries() smarter about fitting Transactions into a Blob

This commit is contained in:
Rob Walker
2018-07-24 19:42:37 -07:00
parent 195098ca2b
commit 33bd1229d9

View File

@ -78,33 +78,58 @@ pub fn next_entries_mut(
cur_hashes: &mut u64, cur_hashes: &mut u64,
transactions: Vec<Transaction>, transactions: Vec<Transaction>,
) -> Vec<Entry> { ) -> Vec<Entry> {
if transactions.is_empty() { // TODO: find a magic number that works better than | ?
// V
if transactions.is_empty() || transactions.len() == 1 {
vec![Entry::new_mut(start_hash, cur_hashes, transactions, false)] vec![Entry::new_mut(start_hash, cur_hashes, transactions, false)]
} else { } else {
let mut chunk_len = transactions.len(); let mut start = 0;
let mut entries = Vec::new();
// check for fit, make sure they can be serialized while start < transactions.len() {
while !Entry::will_fit(transactions[0..chunk_len].to_vec()) { let mut chunk_end = transactions.len();
chunk_len /= 2; let mut upper = chunk_end;
} let mut lower = start;
let mut next = chunk_end; // be optimistic that all will fit
let mut num_chunks = if transactions.len() % chunk_len == 0 { // binary search for how many transactions will fit in an Entry (i.e. a BLOB)
transactions.len() / chunk_len loop {
} else { debug!(
transactions.len() / chunk_len + 1 "chunk_end {}, upper {} lower {} next {} transactions.len() {}",
}; chunk_end,
upper,
let mut entries = Vec::with_capacity(num_chunks); lower,
next,
for chunk in transactions.chunks(chunk_len) { transactions.len()
num_chunks -= 1; );
if Entry::will_fit(transactions[start..chunk_end].to_vec()) {
next = (upper + chunk_end) / 2;
lower = chunk_end;
debug!(
"chunk_end {} fits, maybe too well? trying {}",
chunk_end, next
);
} else {
next = (lower + chunk_end) / 2;
upper = chunk_end;
debug!("chunk_end {} doesn't fit! trying {}", chunk_end, next);
}
// same as last time
if next == chunk_end {
debug!("converged on chunk_end {}", chunk_end);
break;
}
chunk_end = next;
}
entries.push(Entry::new_mut( entries.push(Entry::new_mut(
start_hash, start_hash,
cur_hashes, cur_hashes,
chunk.to_vec(), transactions[start..chunk_end].to_vec(),
num_chunks > 0, transactions.len() - chunk_end > 0,
)); ));
start = chunk_end;
} }
entries entries
} }
} }
@ -217,7 +242,7 @@ mod tests {
transactions.extend(large_transactions); transactions.extend(large_transactions);
let entries0 = next_entries(&id, 0, transactions.clone()); let entries0 = next_entries(&id, 0, transactions.clone());
assert_eq!(entries0.len(), 5); assert!(entries0.len() > 2);
assert!(entries0[0].has_more); assert!(entries0[0].has_more);
assert!(!entries0[entries0.len() - 1].has_more); assert!(!entries0[entries0.len() - 1].has_more);
assert!(entries0.verify(&id)); assert!(entries0.verify(&id));