use super::IsStrategy;
use crate::defaults::io::READ_BUFFER_SIZE;
use crate::metrics::ChunkMetrics;
#[derive(Debug, Clone)]
pub struct StaticStrategy {
pub chunk_size: usize,
pub config: ChunkConfig,
}
impl StaticStrategy {
pub fn conservative() -> Self {
let config = ChunkConfig {
overlap_size: 1024,
low_memory_mode: true,
};
let base_size = 4 * 1024 * 1024; let aligned_size = align_to_block_size(base_size, get_optimal_block_size());
Self {
chunk_size: aligned_size,
config,
}
}
pub fn optimal_for_file(file_size: u64) -> Self {
let config = ChunkConfig::optimal(file_size);
let chunk_size = optimal_chunk_size(file_size, None);
Self { chunk_size, config }
}
pub fn with_config(config: ChunkConfig) -> Self {
let aligned_size = align_to_block_size(READ_BUFFER_SIZE, get_optimal_block_size());
Self {
chunk_size: aligned_size,
config,
}
}
}
impl Default for StaticStrategy {
fn default() -> Self {
let default_size = crate::defaults::SystemDefaults::DEFAULT_CHUNK_SIZE;
let aligned_size = align_to_block_size(default_size, get_optimal_block_size());
Self {
chunk_size: aligned_size,
config: ChunkConfig::default(),
}
}
}
impl IsStrategy for StaticStrategy {
fn initial_chunk_size(&self) -> usize {
self.chunk_size
}
fn adapt_size(&mut self, _metrics: &ChunkMetrics, current_size: usize) -> usize {
current_size }
fn should_adapt(&self, _metrics: &ChunkMetrics) -> bool {
false }
}
#[derive(Debug, Clone)]
pub struct ChunkConfig {
pub overlap_size: usize,
pub low_memory_mode: bool,
}
impl Default for ChunkConfig {
fn default() -> Self {
Self {
overlap_size: 1024, low_memory_mode: false,
}
}
}
impl ChunkConfig {
pub fn optimal(_file_size: u64) -> Self {
Self {
overlap_size: 1024,
low_memory_mode: false,
}
}
}
pub fn align_to_block_size(size: usize, block_size: usize) -> usize {
size.div_ceil(block_size) * block_size
}
pub fn get_optimal_block_size() -> usize {
4096 }
pub fn optimal_chunk_size(file_size: u64, _available_memory: Option<usize>) -> usize {
crate::defaults::SystemDefaults::optimal_chunk_for_file(file_size)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn aligned_to_blocks() {
let block_size = 4096;
assert_eq!(align_to_block_size(4096, block_size), 4096);
assert_eq!(align_to_block_size(8192, block_size), 8192);
assert_eq!(align_to_block_size(4097, block_size), 8192);
assert_eq!(align_to_block_size(1000, block_size), 4096);
assert_eq!(align_to_block_size(9000, block_size), 12288);
assert_eq!(align_to_block_size(0, block_size), 0);
assert_eq!(align_to_block_size(1, block_size), 4096);
}
#[test]
fn optimal_chunk_sizes_are_aligned() {
let block_size = get_optimal_block_size();
let small_chunk = optimal_chunk_size(500_000, None);
let medium_chunk = optimal_chunk_size(50_000_000, None);
let large_chunk = optimal_chunk_size(500_000_000, None);
assert_eq!(small_chunk % block_size, 0);
assert_eq!(medium_chunk % block_size, 0);
assert_eq!(large_chunk % block_size, 0);
println!("Block-aligned chunk sizes:");
println!(" Small file (500KB): {} bytes", small_chunk);
println!(" Medium file (50MB): {} bytes", medium_chunk);
println!(" Large file (500MB): {} bytes", large_chunk);
}
}