Optimize POW read (#3035)

* Optimize POW read

This functionality is used to deserialize header (from network or from
DB), it was taking up to 40% cpu time during initial header sync. This
PR brings it down to 3-4%. Function read_number would look better as
closure, unfortunately the compliler doesn't inline it in this case, so
it would be 2x slower.

* Remove unused code
This commit is contained in:
hashmap 2019-09-10 15:14:33 +02:00 committed by GitHub
parent 80a8f76c4c
commit d90b1c2723
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 27 deletions

View file

@ -42,10 +42,10 @@ use crate::util::RwLock;
pub const PROTOCOL_VERSION: u32 = 1;
/// Automated testing edge_bits
pub const AUTOMATED_TESTING_MIN_EDGE_BITS: u8 = 9;
pub const AUTOMATED_TESTING_MIN_EDGE_BITS: u8 = 10;
/// Automated testing proof size
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 4;
pub const AUTOMATED_TESTING_PROOF_SIZE: usize = 8;
/// User testing edge_bits
pub const USER_TESTING_MIN_EDGE_BITS: u8 = 15;

View file

@ -391,6 +391,23 @@ impl Proof {
}
}
#[inline(always)]
fn read_number(bits: &Vec<u8>, bit_start: usize, bit_count: usize) -> u64 {
if bit_count == 0 {
return 0;
}
let mut buf: [u8; 8] = [0; 8];
let mut byte_start = bit_start / 8;
if byte_start + 8 > bits.len() {
byte_start = bits.len() - 8;
}
buf.copy_from_slice(&bits[byte_start..byte_start + 8]);
buf.reverse();
let mut nonce = u64::from_be_bytes(buf);
nonce = nonce << 64 - (bit_start - byte_start * 8) - bit_count;
nonce >> 64 - bit_count
}
impl Readable for Proof {
fn read(reader: &mut dyn Reader) -> Result<Proof, ser::Error> {
let edge_bits = reader.read_u8()?;
@ -405,25 +422,16 @@ impl Readable for Proof {
let bytes_len = BitVec::bytes_len(bits_len);
let bits = reader.read_fixed_bytes(bytes_len)?;
// set our nonces from what we read in the bitvec
let bitvec = BitVec { bits };
for n in 0..global::proofsize() {
let mut nonce = 0;
for bit in 0..nonce_bits {
if bitvec.bit_at(n * nonce_bits + (bit as usize)) {
nonce |= 1 << bit;
}
}
nonces.push(nonce);
nonces.push(read_number(&bits, n * nonce_bits, nonce_bits));
}
// check the last bits of the last byte are zeroed, we don't use them but
// still better to enforce to avoid any malleability
for n in bits_len..(bytes_len * 8) {
if bitvec.bit_at(n) {
//// check the last bits of the last byte are zeroed, we don't use them but
//// still better to enforce to avoid any malleability
let end_of_data = global::proofsize() * nonce_bits;
if read_number(&bits, end_of_data, bytes_len * 8 - end_of_data) != 0 {
return Err(ser::Error::CorruptedData);
}
}
Ok(Proof { edge_bits, nonces })
}
@ -469,8 +477,4 @@ impl BitVec {
fn set_bit_at(&mut self, pos: usize) {
self.bits[pos / 8] |= 1 << (pos % 8) as u8;
}
fn bit_at(&self, pos: usize) -> bool {
self.bits[pos / 8] & (1 << (pos % 8) as u8) != 0
}
}

View file

@ -269,7 +269,7 @@ fn empty_block_serialized_size() {
let b = new_block(vec![], &keychain, &builder, &prev, &key_id);
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &b).expect("serialization failed");
let target_len = 1_107;
let target_len = 1_112;
assert_eq!(vec.len(), target_len);
}
@ -284,7 +284,7 @@ fn block_single_tx_serialized_size() {
let b = new_block(vec![&tx1], &keychain, &builder, &prev, &key_id);
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &b).expect("serialization failed");
let target_len = 2_689;
let target_len = 2_694;
assert_eq!(vec.len(), target_len);
}
@ -299,7 +299,7 @@ fn empty_compact_block_serialized_size() {
let cb: CompactBlock = b.into();
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &cb).expect("serialization failed");
let target_len = 1_115;
let target_len = 1_120;
assert_eq!(vec.len(), target_len);
}
@ -315,7 +315,7 @@ fn compact_block_single_tx_serialized_size() {
let cb: CompactBlock = b.into();
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &cb).expect("serialization failed");
let target_len = 1_121;
let target_len = 1_126;
assert_eq!(vec.len(), target_len);
}
@ -335,7 +335,7 @@ fn block_10_tx_serialized_size() {
let b = new_block(txs.iter().collect(), &keychain, &builder, &prev, &key_id);
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &b).expect("serialization failed");
let target_len = 16_927;
let target_len = 16_932;
assert_eq!(vec.len(), target_len,);
}
@ -356,7 +356,7 @@ fn compact_block_10_tx_serialized_size() {
let cb: CompactBlock = b.into();
let mut vec = Vec::new();
ser::serialize_default(&mut vec, &cb).expect("serialization failed");
let target_len = 1_175;
let target_len = 1_180;
assert_eq!(vec.len(), target_len,);
}