mirror of
https://github.com/mimblewimble/grin.git
synced 2025-04-21 09:51:14 +03:00
Optimizations for txhashset rewind (#1528)
This commit is contained in:
parent
d3a5ee130f
commit
26244ef9dd
3 changed files with 96 additions and 13 deletions
|
@ -140,6 +140,13 @@ impl ChainStore {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_hash_by_height(&self, height: u64) -> Result<Hash, Error> {
|
||||
option_to_not_found(
|
||||
self.db.get_ser(&u64_to_key(HEADER_HEIGHT_PREFIX, height)),
|
||||
&format!("Hash at height: {}", height),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_header_by_height(&self, height: u64) -> Result<BlockHeader, Error> {
|
||||
option_to_not_found(
|
||||
self.db.get_ser(&u64_to_key(HEADER_HEIGHT_PREFIX, height)),
|
||||
|
|
|
@ -1214,8 +1214,8 @@ fn input_pos_to_rewind(
|
|||
head_header: &BlockHeader,
|
||||
batch: &Batch,
|
||||
) -> Result<Bitmap, Error> {
|
||||
let mut bitmap = Bitmap::create();
|
||||
let mut current = head_header.hash();
|
||||
let mut height = head_header.height;
|
||||
|
||||
if head_header.height < block_header.height {
|
||||
debug!(
|
||||
|
@ -1224,27 +1224,42 @@ fn input_pos_to_rewind(
|
|||
head_header.height,
|
||||
block_header.height
|
||||
);
|
||||
return Ok(bitmap);
|
||||
return Ok(Bitmap::create());
|
||||
}
|
||||
|
||||
//
|
||||
// TODO - rework this loop to use Bitmap::fast_or() on a vec of bitmaps.
|
||||
//
|
||||
loop {
|
||||
if current == block_header.hash() {
|
||||
break;
|
||||
// Batching up the block input bitmaps, and running fast_or() on every batch of 256 bitmaps.
|
||||
// so to avoid maintaining a huge vec of bitmaps.
|
||||
let bitmap_fast_or = |b_res, block_input_bitmaps: &mut Vec<Bitmap>| -> Option<Bitmap> {
|
||||
if let Some(b) = b_res {
|
||||
block_input_bitmaps.push(b);
|
||||
if block_input_bitmaps.len() < 256 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
let bitmap = Bitmap::fast_or(&block_input_bitmaps.iter().collect::<Vec<&Bitmap>>());
|
||||
block_input_bitmaps.clear();
|
||||
block_input_bitmaps.push(bitmap.clone());
|
||||
Some(bitmap)
|
||||
};
|
||||
|
||||
let mut block_input_bitmaps: Vec<Bitmap> = vec![];
|
||||
let bh = block_header.hash();
|
||||
|
||||
while current != bh {
|
||||
// We cache recent block headers and block_input_bitmaps
|
||||
// internally in our db layer (commit_index).
|
||||
// I/O should be minimized or eliminated here for most
|
||||
// rewind scenarios.
|
||||
let current_header = commit_index.get_block_header(¤t)?;
|
||||
let input_bitmap_res = batch.get_block_input_bitmap(¤t);
|
||||
if let Ok(b) = input_bitmap_res {
|
||||
bitmap.or_inplace(&b);
|
||||
if let Ok(b_res) = batch.get_block_input_bitmap(¤t) {
|
||||
bitmap_fast_or(Some(b_res), &mut block_input_bitmaps);
|
||||
}
|
||||
current = current_header.previous;
|
||||
if height == 0 {
|
||||
break;
|
||||
}
|
||||
height -= 1;
|
||||
current = commit_index.get_hash_by_height(height)?;
|
||||
}
|
||||
|
||||
let bitmap = bitmap_fast_or(None, &mut block_input_bitmaps).unwrap();
|
||||
Ok(bitmap)
|
||||
}
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
extern crate chrono;
|
||||
extern crate croaring;
|
||||
extern crate rand;
|
||||
|
||||
use chrono::prelude::Utc;
|
||||
use croaring::Bitmap;
|
||||
use rand::Rng;
|
||||
|
||||
|
@ -97,3 +99,62 @@ fn test_a_big_bitmap() {
|
|||
let serialized_buffer = bitmap.serialize();
|
||||
assert_eq!(serialized_buffer.len(), 230);
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn bench_fast_or() {
|
||||
let nano_to_millis = 1.0 / 1_000_000.0;
|
||||
|
||||
let bitmaps_number = 256;
|
||||
let size_of_each_bitmap = 1_000;
|
||||
|
||||
let init_bitmaps = || -> Vec<Bitmap> {
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut bitmaps = vec![];
|
||||
for _ in 0..bitmaps_number {
|
||||
let mut bitmap = Bitmap::create();
|
||||
for _ in 0..size_of_each_bitmap {
|
||||
let n = rng.gen_range(0, 1_000_000);
|
||||
bitmap.add(n);
|
||||
}
|
||||
bitmaps.push(bitmap);
|
||||
}
|
||||
bitmaps
|
||||
};
|
||||
|
||||
let mut bitmaps = init_bitmaps();
|
||||
let mut bitmap = Bitmap::create();
|
||||
let start = Utc::now().timestamp_nanos();
|
||||
for _ in 0..bitmaps_number {
|
||||
bitmap.or_inplace(&bitmaps.pop().unwrap());
|
||||
}
|
||||
let fin = Utc::now().timestamp_nanos();
|
||||
let dur_ms = (fin - start) as f64 * nano_to_millis;
|
||||
println!(
|
||||
" or_inplace(): {:9.3?}ms. bitmap cardinality: {}",
|
||||
dur_ms,
|
||||
bitmap.cardinality()
|
||||
);
|
||||
|
||||
let bitmaps = init_bitmaps();
|
||||
let start = Utc::now().timestamp_nanos();
|
||||
let bitmap = Bitmap::fast_or(&bitmaps.iter().map(|x| x).collect::<Vec<&Bitmap>>());
|
||||
let fin = Utc::now().timestamp_nanos();
|
||||
let dur_ms = (fin - start) as f64 * nano_to_millis;
|
||||
println!(
|
||||
" fast_or(): {:9.3?}ms. bitmap cardinality: {}",
|
||||
dur_ms,
|
||||
bitmap.cardinality()
|
||||
);
|
||||
|
||||
let bitmaps = init_bitmaps();
|
||||
let start = Utc::now().timestamp_nanos();
|
||||
let bitmap = Bitmap::fast_or_heap(&bitmaps.iter().map(|x| x).collect::<Vec<&Bitmap>>());
|
||||
let fin = Utc::now().timestamp_nanos();
|
||||
let dur_ms = (fin - start) as f64 * nano_to_millis;
|
||||
println!(
|
||||
"fast_or_heap(): {:9.3?}ms. bitmap cardinality: {}",
|
||||
dur_ms,
|
||||
bitmap.cardinality()
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue