Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions benches/fastpfor_benchmark.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use core::ops::Range;
use std::hint::black_box;
use std::io::Cursor;
use std::num::NonZeroU32;

use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use fastpfor::rust::{FastPFOR, Integer, BLOCK_SIZE_128, BLOCK_SIZE_256, DEFAULT_PAGE_SIZE};
use rand::rngs::StdRng;
use rand::{RngExt as _, SeedableRng};
use std::hint::black_box;
use std::io::Cursor;

const SIZES: &[usize; 2] = &[1024, 4096];
const SEED: u64 = 456;
Expand Down Expand Up @@ -92,7 +94,7 @@ fn compress_data(codec: &mut FastPFOR, data: &[u32]) -> usize {
}

/// Helper function to compress data and return compressed buffer
fn prepare_compressed_data(data: &[u32], block_size: u32) -> Vec<u32> {
fn prepare_compressed_data(data: &[u32], block_size: NonZeroU32) -> Vec<u32> {
let mut codec = FastPFOR::new(DEFAULT_PAGE_SIZE, block_size);
let mut compressed = vec![0u32; data.len() * 2];
let mut input_offset = Cursor::new(0);
Expand Down
28 changes: 16 additions & 12 deletions src/rust/integer_compression/fastpfor.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use std::io::Cursor;
use std::num::NonZeroU32;

use crate::rust::cursor::IncrementCursor;
use crate::rust::integer_compression::{bitpacking, helpers};
use crate::rust::{bytebuffer, FastPForResult, Integer, Skippable};

/// Block size constant for 256 integers per block
pub const BLOCK_SIZE_256: u32 = 256;
pub const BLOCK_SIZE_256: NonZeroU32 = NonZeroU32::new(256).unwrap();

/// Block size constant for 128 integers per block
pub const BLOCK_SIZE_128: u32 = 128;
pub const BLOCK_SIZE_128: NonZeroU32 = NonZeroU32::new(128).unwrap();

/// Overhead cost (in bits) for storing each exception's position in the block
const OVERHEAD_OF_EACH_EXCEPT: u32 = 8;

/// Default page size in number of integers
pub const DEFAULT_PAGE_SIZE: u32 = 65536;
pub const DEFAULT_PAGE_SIZE: NonZeroU32 = NonZeroU32::new(65536).unwrap();
Comment thread
CommanderStorm marked this conversation as resolved.

/// Fast Patched Frame-of-Reference ([`FastPFOR`](https://github.com/lemire/FastPFor)) integer compression codec.
///
Expand Down Expand Up @@ -73,7 +74,7 @@ impl Skippable for FastPFOR {
output_offset: &mut Cursor<u32>,
num: u32,
) -> FastPForResult<()> {
if inlength == 0 && self.block_size == BLOCK_SIZE_128 {
if inlength == 0 && self.block_size == BLOCK_SIZE_128.get() {
// Return early if there is no data to uncompress and block size is 128
return Ok(());
}
Expand Down Expand Up @@ -142,7 +143,9 @@ impl FastPFOR {
/// Creates codec with specified page and block sizes.
///
/// Pre-allocates buffers for metadata and exception storage.
pub fn new(page_size: u32, block_size: u32) -> FastPFOR {
pub fn new(page_size: NonZeroU32, block_size: NonZeroU32) -> FastPFOR {
let page_size = page_size.get();
let block_size = block_size.get();
FastPFOR {
page_size,
block_size,
Expand Down Expand Up @@ -450,7 +453,7 @@ mod tests {
fn fastpfor_test() {
let mut codec1 = FastPFOR::default();
let mut codec2 = FastPFOR::default();
let mut data = vec![0u32; BLOCK_SIZE_256 as usize];
let mut data = vec![0u32; BLOCK_SIZE_256.get() as usize];
data[126] = -1i32 as u32;
let mut out_buf = vec![0; data.len() * 4];
let mut input_offset = Cursor::new(0);
Expand Down Expand Up @@ -480,7 +483,9 @@ mod tests {
.unwrap();
let answer = out_buf_uncomp[..output_offset.position() as usize].to_vec();

for k in 0..BLOCK_SIZE_256 {
assert_eq!(answer.len(), BLOCK_SIZE_256.get() as usize);
assert_eq!(data.len(), BLOCK_SIZE_256.get() as usize);
for k in 0..BLOCK_SIZE_256.get() {
assert_eq!(answer[k as usize], data[k as usize], "bug in {k}");
}
}
Expand All @@ -489,10 +494,7 @@ mod tests {
fn fastpfor_test_128() {
let mut codec1 = FastPFOR::new(DEFAULT_PAGE_SIZE, BLOCK_SIZE_128);
let mut codec2 = FastPFOR::new(DEFAULT_PAGE_SIZE, BLOCK_SIZE_128);
let mut data = vec![0; BLOCK_SIZE_128 as usize];
for i in 0..BLOCK_SIZE_128 {
data[i as usize] = 0;
}
let mut data = vec![0; BLOCK_SIZE_128.get() as usize];
data[126] = -1i32 as u32;
let mut out_buf = vec![0; data.len() * 4];
let mut input_offset = Cursor::new(0);
Expand Down Expand Up @@ -522,7 +524,9 @@ mod tests {
.unwrap();
let answer = out_buf_uncomp[..output_offset.position() as usize].to_vec();

for k in 0..BLOCK_SIZE_128 {
assert_eq!(answer.len(), BLOCK_SIZE_128.get() as usize);
assert_eq!(data.len(), BLOCK_SIZE_128.get() as usize);
for k in 0..BLOCK_SIZE_128.get() {
assert_eq!(answer[k as usize], data[k as usize], "bug in {k}");
}
}
Expand Down
11 changes: 6 additions & 5 deletions tests/basic_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![allow(clippy::needless_range_loop)]

use std::io::Cursor;
use std::num::NonZeroU32;

use fastpfor::rust::{
fast_pack, fast_unpack, Composition, FastPFOR, Integer, VariableByte, BLOCK_SIZE_128,
Expand Down Expand Up @@ -381,10 +382,10 @@ fn test_random_numbers() {
#[test]
fn test_fastpfor_headless_compress_unfit_pagesize() {
// The input size is a multiple of 128 but does not fit the page size
let test_input_size = 512 + BLOCK_SIZE_128;
let page_size = 512;
let test_input_size = BLOCK_SIZE_128.checked_add(512).unwrap();
let page_size = NonZeroU32::new(512).unwrap();

let input: Vec<u32> = (0..test_input_size).collect();
let input: Vec<u32> = (0..test_input_size.get()).collect();
let mut output: Vec<u32> = vec![0; input.len()];
let mut decoded: Vec<u32> = vec![0; input.len()];
let mut input_offset = Cursor::new(0u32);
Expand Down Expand Up @@ -419,8 +420,8 @@ fn test_fastpfor_headless_compress_unfit_pagesize() {

#[test]
fn test_exception_value_vector_resizes() {
let page_size = 512;
let test_input_size = page_size * 2;
let page_size = NonZeroU32::new(512).unwrap();
let test_input_size = page_size.get() * 2;

// every even index value is large which will trigger exception buffer to be resize
let input: Vec<u32> = (0..test_input_size)
Expand Down
4 changes: 2 additions & 2 deletions tests/cpp_compat_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ fn test_rust_decompresses_cpp_encoded_data() {
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);

for n in test_input_sizes() {
for input in get_test_cases(n + rust::BLOCK_SIZE_128 as usize) {
for input in get_test_cases(n + rust::BLOCK_SIZE_128.get() as usize) {
// Buffer for the C++ encoded
let mut compressed_buffer = vec![0; input.len()];

Expand Down Expand Up @@ -58,7 +58,7 @@ fn test_rust_and_cpp_fastpfor32_compression_matches() {
let mut codec_rs = rust::FastPFOR::new(rust::DEFAULT_PAGE_SIZE, rust::BLOCK_SIZE_128);

for n in test_input_sizes() {
for input in get_test_cases(n + rust::BLOCK_SIZE_128 as usize) {
for input in get_test_cases(n + rust::BLOCK_SIZE_128.get() as usize) {
// Buffer for the C++ encoded
let mut compressed_buffer = vec![0; input.len()];

Expand Down