Created
March 9, 2019 11:27
-
-
Save samcday/97ae61d66fc37b7374c4d96850ff3fde to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate bencher; | |
use bencher::Bencher; | |
use lazy_static::lazy_static; | |
use oxideboy::{interrupt, ppu, simple_diff, Gameboy, Model}; | |
use snap; | |
lazy_static! { | |
static ref DIFF_STATES: (Vec<u8>, Vec<u8>) = { | |
let rom = include_bytes!("../tests/blargg/mem_timing.gb").to_vec(); | |
let mut gb = Gameboy::new(Model::DMG, rom); | |
let mut base_state = Vec::new(); | |
let mut new_state = Vec::new(); | |
for _ in 0..60 { | |
while !gb.new_frame { | |
gb.run_instruction(); | |
} | |
gb.run_instruction(); | |
gb.save_state(&mut base_state); | |
} | |
for _ in 0..60 { | |
while !gb.new_frame { | |
gb.run_instruction(); | |
} | |
gb.run_instruction(); | |
gb.save_state(&mut new_state); | |
} | |
(base_state, new_state) | |
}; | |
} | |
fn diff_small(bench: &mut Bencher) { | |
let mut diff_out = Vec::new(); | |
let base_state = &DIFF_STATES.0; | |
let new_state = &DIFF_STATES.1; | |
simple_diff::generate(&base_state, &new_state, &mut diff_out); | |
let cap = diff_out.capacity(); | |
let size = diff_out.len(); | |
bench.iter(|| { | |
diff_out.clear(); | |
simple_diff::generate(&base_state, &new_state, &mut diff_out); | |
assert_eq!(diff_out.capacity(), cap); | |
assert_eq!(diff_out.len(), size); | |
}); | |
} | |
benchmark_group!( | |
diff_small, | |
); | |
benchmark_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt}; | |
use std::io::prelude::*; | |
/// The number of bytes that must be identical before a chunk is finished off. | |
pub const CHUNK_END_WINDOW: usize = 16; | |
/// Generates a diff between the base data and the new data. Results are written into the diff Vec. | |
pub fn generate(base: &[u8], new: &[u8], diff: &mut Vec<u8>) { | |
// This whole deal only works if our two blobs are the same size. | |
// assert_eq!(base.len(), new.len()); | |
let mut chunk_start: usize = 0; | |
let mut chunk_end: usize = 0; | |
let mut in_chunk = false; | |
let mut chunk_count = 0; | |
// This will be the chunk count, we'll fill it in at the end. | |
diff.write_u32::<LittleEndian>(0).unwrap(); | |
for (i, (l, r)) in base.iter().zip(new.iter()).enumerate() { | |
let eq = l == r; | |
if !eq { | |
if !in_chunk { | |
in_chunk = true; | |
chunk_start = i; | |
} | |
chunk_end = i; | |
} | |
if eq && in_chunk { | |
if i - chunk_end > CHUNK_END_WINDOW { | |
chunk_count += 1; | |
diff.write_u32::<LittleEndian>(chunk_start as u32).unwrap(); | |
diff.write_u32::<LittleEndian>((chunk_end - chunk_start + 1) as u32) | |
.unwrap(); | |
diff.write(&new[chunk_start..chunk_end + 1]).unwrap(); | |
in_chunk = false; | |
} | |
} | |
} | |
if in_chunk { | |
chunk_count += 1; | |
diff.write_u32::<LittleEndian>(chunk_start as u32).unwrap(); | |
diff.write_u32::<LittleEndian>((chunk_end - chunk_start + 1) as u32) | |
.unwrap(); | |
diff.write(&new[chunk_start..chunk_end + 1]).unwrap(); | |
} | |
LittleEndian::write_u32(&mut diff[0..4], chunk_count); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment