use crate::error::BatchError;
#[derive(Debug, Clone)]
pub struct BatchConfig {
pub batch_size: usize,
pub thread_count: Option<usize>,
pub use_simd: bool,
pub chunk_size: usize,
pub memory_limit: Option<usize>,
pub parallel: bool,
pub deterministic_order: bool,
}
impl Default for BatchConfig {
fn default() -> Self {
Self {
batch_size: 10_000,
thread_count: None,
use_simd: true,
chunk_size: 1_000,
memory_limit: None,
parallel: false,
deterministic_order: false,
}
}
}
impl BatchConfig {
pub fn new() -> Self {
Self::default()
}
pub fn fast() -> Self {
Self {
batch_size: 100_000,
thread_count: None, use_simd: true,
chunk_size: 10_000,
memory_limit: None,
parallel: true,
deterministic_order: false,
}
}
pub fn balanced() -> Self {
Self {
batch_size: 50_000,
thread_count: None,
use_simd: true,
chunk_size: 5_000,
memory_limit: Some(100 * 1024 * 1024), parallel: true,
deterministic_order: false,
}
}
pub fn memory_efficient() -> Self {
Self {
batch_size: 10_000,
thread_count: Some(2),
use_simd: true,
chunk_size: 100,
memory_limit: Some(10 * 1024 * 1024), parallel: true,
deterministic_order: false,
}
}
pub fn with_batch_size(mut self, size: usize) -> Self {
self.batch_size = size;
self
}
pub fn with_thread_count(mut self, count: Option<usize>) -> Self {
self.thread_count = count;
self
}
pub fn with_simd(mut self, enabled: bool) -> Self {
self.use_simd = enabled;
self
}
pub fn with_chunk_size(mut self, size: usize) -> Self {
self.chunk_size = size;
self
}
pub fn with_memory_limit(mut self, limit: Option<usize>) -> Self {
self.memory_limit = limit;
self
}
pub fn with_parallel(mut self, enabled: bool) -> Self {
self.parallel = enabled;
self
}
pub fn with_deterministic_order(mut self, enabled: bool) -> Self {
self.deterministic_order = enabled;
self
}
pub fn validate(&self) -> Result<(), BatchError> {
if self.batch_size == 0 {
return Err(BatchError::invalid_config("batch_size must be greater than 0"));
}
if self.chunk_size == 0 {
return Err(BatchError::invalid_config("chunk_size must be greater than 0"));
}
if let Some(count) = self.thread_count {
if count == 0 {
return Err(BatchError::invalid_config("thread_count must be greater than 0"));
}
}
if let Some(limit) = self.memory_limit {
if limit == 0 {
return Err(BatchError::invalid_config("memory_limit must be greater than 0"));
}
}
Ok(())
}
pub fn effective_thread_count(&self) -> usize {
self.thread_count.unwrap_or_else(|| {
rayon::current_num_threads()
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_config() {
let config = BatchConfig::default();
assert_eq!(config.batch_size, 10_000);
assert!(config.thread_count.is_none());
assert!(config.use_simd);
assert_eq!(config.chunk_size, 1_000);
assert!(config.memory_limit.is_none());
assert!(!config.parallel);
assert!(!config.deterministic_order);
}
#[test]
fn test_fast_preset() {
let config = BatchConfig::fast();
assert_eq!(config.batch_size, 100_000);
assert!(config.parallel);
assert_eq!(config.chunk_size, 10_000);
}
#[test]
fn test_balanced_preset() {
let config = BatchConfig::balanced();
assert_eq!(config.batch_size, 50_000);
assert!(config.parallel);
assert!(config.memory_limit.is_some());
}
#[test]
fn test_memory_efficient_preset() {
let config = BatchConfig::memory_efficient();
assert_eq!(config.chunk_size, 100);
assert!(config.memory_limit.is_some());
}
#[test]
fn test_builder_pattern() {
let config = BatchConfig::new()
.with_batch_size(50_000)
.with_thread_count(Some(4))
.with_chunk_size(500)
.with_parallel(true);
assert_eq!(config.batch_size, 50_000);
assert_eq!(config.thread_count, Some(4));
assert_eq!(config.chunk_size, 500);
assert!(config.parallel);
}
#[test]
fn test_validation_valid() {
let config = BatchConfig::default();
assert!(config.validate().is_ok());
}
#[test]
fn test_validation_invalid_batch_size() {
let config = BatchConfig::default().with_batch_size(0);
assert!(config.validate().is_err());
}
#[test]
fn test_validation_invalid_chunk_size() {
let config = BatchConfig::default().with_chunk_size(0);
assert!(config.validate().is_err());
}
#[test]
fn test_validation_invalid_thread_count() {
let config = BatchConfig::default().with_thread_count(Some(0));
assert!(config.validate().is_err());
}
}