use crate::compression::dict_zip::compression_types::{
Match, CompressionType, encode_match, decode_match, BitWriter, BitReader,
calculate_encoding_cost, choose_best_compression_type_reference
};
use crate::compression::dict_zip::{SuffixArrayDictionary, DictionaryBuilder};
use crate::compression::simd_pattern_match::{
SimdPatternMatcher, SimdPatternConfig
};
use crate::memory::simd_ops::{SimdMemOps, get_global_simd_ops};
use crate::memory::{SecureMemoryPool, CacheOptimizedAllocator, CacheLayoutConfig};
use crate::system::cpu_features::{CpuFeatures, get_cpu_features};
use crate::error::{Result, ZiporaError};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::collections::HashMap;
use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CompressionTier {
Scalar,
#[cfg(target_arch = "aarch64")]
Neon,
Popcnt,
Bmi2,
Avx2,
#[cfg(feature = "avx512")]
Avx512,
}
impl CompressionTier {
pub fn is_supported(self, cpu_features: &CpuFeatures) -> bool {
match self {
CompressionTier::Scalar => true, #[cfg(target_arch = "aarch64")]
CompressionTier::Neon => cpu_features.has_neon,
CompressionTier::Popcnt => cpu_features.has_popcnt,
CompressionTier::Bmi2 => cpu_features.has_bmi2,
CompressionTier::Avx2 => cpu_features.has_avx2,
#[cfg(feature = "avx512")]
CompressionTier::Avx512 => cpu_features.has_avx512f && cpu_features.has_avx512vl,
}
}
pub fn select_optimal(cpu_features: &CpuFeatures) -> Self {
#[cfg(feature = "avx512")]
if cpu_features.has_avx512f && cpu_features.has_avx512vl && cpu_features.has_avx512bw {
return CompressionTier::Avx512;
}
if cpu_features.has_avx2 && cpu_features.has_bmi2 {
return CompressionTier::Avx2;
}
if cpu_features.has_bmi2 {
return CompressionTier::Bmi2;
}
if cpu_features.has_popcnt {
return CompressionTier::Popcnt;
}
#[cfg(target_arch = "aarch64")]
if cpu_features.has_neon {
return CompressionTier::Neon;
}
CompressionTier::Scalar
}
pub fn name(self) -> &'static str {
match self {
CompressionTier::Scalar => "Scalar",
#[cfg(target_arch = "aarch64")]
CompressionTier::Neon => "NEON",
CompressionTier::Popcnt => "POPCNT",
CompressionTier::Bmi2 => "BMI2",
CompressionTier::Avx2 => "AVX2",
#[cfg(feature = "avx512")]
CompressionTier::Avx512 => "AVX-512",
}
}
pub fn performance_multiplier(self) -> f64 {
match self {
CompressionTier::Scalar => 1.0,
#[cfg(target_arch = "aarch64")]
CompressionTier::Neon => 2.5,
CompressionTier::Popcnt => 1.5,
CompressionTier::Bmi2 => 3.0,
CompressionTier::Avx2 => 5.0,
#[cfg(feature = "avx512")]
CompressionTier::Avx512 => 8.0,
}
}
}
impl std::fmt::Display for CompressionTier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CompressionParallelMode {
X1 = 1,
X2 = 2,
X4 = 4,
X8 = 8,
}
impl CompressionParallelMode {
pub fn stream_count(self) -> usize {
self as usize
}
pub fn is_supported(self, cpu_features: &CpuFeatures) -> bool {
match self {
CompressionParallelMode::X1 => true, CompressionParallelMode::X2 => cpu_features.logical_cores >= 2,
CompressionParallelMode::X4 => cpu_features.logical_cores >= 4 && cpu_features.has_avx2,
CompressionParallelMode::X8 => cpu_features.logical_cores >= 8 && cpu_features.has_avx2,
}
}
pub fn select_optimal(cpu_features: &CpuFeatures) -> Self {
if cpu_features.logical_cores >= 8 && cpu_features.has_avx2 {
CompressionParallelMode::X8
} else if cpu_features.logical_cores >= 4 && cpu_features.has_avx2 {
CompressionParallelMode::X4
} else if cpu_features.logical_cores >= 2 {
CompressionParallelMode::X2
} else {
CompressionParallelMode::X1
}
}
}
impl std::fmt::Display for CompressionParallelMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "X{}", self.stream_count())
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SimdLz77Match {
pub pa_zip_match: Match,
pub input_position: usize,
pub distance: usize,
pub length: usize,
pub compression_tier: CompressionTier,
pub parallel_mode: CompressionParallelMode,
pub simd_accelerated: bool,
pub simd_operations: u32,
pub match_time_ns: u64,
pub encoding_cost_bits: usize,
pub efficiency_ratio: f64,
}
impl SimdLz77Match {
pub fn new(
pa_zip_match: Match,
input_position: usize,
distance: usize,
compression_tier: CompressionTier,
parallel_mode: CompressionParallelMode,
simd_accelerated: bool,
) -> Self {
let length = pa_zip_match.length();
let encoding_cost_bits = calculate_encoding_cost(&pa_zip_match);
let efficiency_ratio = Self::calculate_efficiency_ratio(length, encoding_cost_bits);
Self {
pa_zip_match,
input_position,
distance,
length,
compression_tier,
parallel_mode,
simd_accelerated,
simd_operations: 0,
match_time_ns: 0,
encoding_cost_bits,
efficiency_ratio,
}
}
fn calculate_efficiency_ratio(length: usize, encoding_cost_bits: usize) -> f64 {
if encoding_cost_bits == 0 {
return 0.0;
}
let data_bits = length * 8;
data_bits as f64 / encoding_cost_bits as f64
}
pub fn is_better_than(&self, other: &SimdLz77Match) -> bool {
if (self.efficiency_ratio - other.efficiency_ratio).abs() < 0.01 {
if self.length == other.length {
self.simd_accelerated && !other.simd_accelerated
} else {
self.length > other.length
}
} else {
self.efficiency_ratio > other.efficiency_ratio
}
}
pub fn compression_type(&self) -> CompressionType {
self.pa_zip_match.compression_type()
}
}
#[derive(Debug, Clone)]
pub struct SimdLz77Config {
pub enable_simd: bool,
pub compression_tier: Option<CompressionTier>,
pub parallel_mode: CompressionParallelMode,
pub min_match_length: usize,
pub max_match_length: usize,
pub search_window_size: usize,
pub lookahead_buffer_size: usize,
pub max_search_iterations: usize,
pub enable_cache_optimization: bool,
pub enable_prefetch: bool,
pub enable_bmi2: bool,
pub enable_early_termination: bool,
pub early_termination_efficiency: f64,
pub dictionary_config: Option<DictionaryConfig>,
pub pattern_config: SimdPatternConfig,
pub allocator_config: CacheLayoutConfig,
}
#[derive(Debug, Clone)]
pub struct DictionaryConfig {
pub suffix_array: Option<Arc<SuffixArrayDictionary>>,
pub dictionary_text: Option<Arc<Vec<u8>>>,
pub enable_dictionary: bool,
pub max_dictionary_distance: usize,
pub min_dictionary_match: usize,
}
impl Default for DictionaryConfig {
fn default() -> Self {
Self {
suffix_array: None,
dictionary_text: None,
enable_dictionary: false,
max_dictionary_distance: 65536,
min_dictionary_match: 6,
}
}
}
impl Default for SimdLz77Config {
fn default() -> Self {
Self {
enable_simd: true,
compression_tier: None, parallel_mode: CompressionParallelMode::X1,
min_match_length: 3,
max_match_length: 258,
search_window_size: 32768,
lookahead_buffer_size: 258,
max_search_iterations: 4096,
enable_cache_optimization: true,
enable_prefetch: true,
enable_bmi2: true,
enable_early_termination: true,
early_termination_efficiency: 2.0,
dictionary_config: Some(DictionaryConfig::default()),
pattern_config: SimdPatternConfig::default(),
allocator_config: CacheLayoutConfig::sequential(),
}
}
}
impl SimdLz77Config {
pub fn high_performance() -> Self {
let cpu_features = get_cpu_features();
Self {
compression_tier: Some(CompressionTier::select_optimal(cpu_features)),
parallel_mode: CompressionParallelMode::select_optimal(cpu_features),
max_search_iterations: 8192,
early_termination_efficiency: 1.5,
pattern_config: SimdPatternConfig::high_throughput(),
allocator_config: CacheLayoutConfig::read_heavy(),
..Default::default()
}
}
pub fn low_latency() -> Self {
Self {
compression_tier: Some(CompressionTier::Bmi2),
parallel_mode: CompressionParallelMode::X1,
max_search_iterations: 1024,
early_termination_efficiency: 2.5,
pattern_config: SimdPatternConfig::low_latency(),
allocator_config: CacheLayoutConfig::new(),
..Default::default()
}
}
pub fn maximum_parallelism() -> Self {
let cpu_features = get_cpu_features();
Self {
compression_tier: Some(CompressionTier::select_optimal(cpu_features)),
parallel_mode: CompressionParallelMode::X8,
max_search_iterations: 16384,
early_termination_efficiency: 1.2,
pattern_config: SimdPatternConfig::maximum_parallelism(),
allocator_config: CacheLayoutConfig::write_heavy(),
..Default::default()
}
}
pub fn with_dictionary(
suffix_array: Arc<SuffixArrayDictionary>,
dictionary_text: Arc<Vec<u8>>,
) -> Self {
let dictionary_config = DictionaryConfig {
suffix_array: Some(suffix_array),
dictionary_text: Some(dictionary_text),
enable_dictionary: true,
max_dictionary_distance: 65536,
min_dictionary_match: 6,
};
Self {
dictionary_config: Some(dictionary_config),
..Self::high_performance()
}
}
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SimdLz77Stats {
pub total_compressions: u64,
pub total_decompressions: u64,
pub bytes_processed: u64,
pub bytes_produced: u64,
pub total_compression_time_ns: u64,
pub total_decompression_time_ns: u64,
pub total_matches_found: u64,
pub total_simd_operations: u64,
pub avg_match_length: f64,
pub avg_compression_efficiency: f64,
pub simd_hit_rate: f64,
pub tier_usage: HashMap<CompressionTier, u64>,
pub parallel_mode_usage: HashMap<CompressionParallelMode, u64>,
pub compression_type_usage: HashMap<CompressionType, u64>,
}
impl SimdLz77Stats {
pub fn compression_ratio(&self) -> f64 {
if self.bytes_processed == 0 {
1.0
} else {
self.bytes_produced as f64 / self.bytes_processed as f64
}
}
pub fn avg_compression_throughput(&self) -> f64 {
if self.total_compression_time_ns == 0 {
0.0
} else {
(self.bytes_processed as f64) / (self.total_compression_time_ns as f64 / 1_000_000_000.0)
}
}
pub fn avg_decompression_throughput(&self) -> f64 {
if self.total_decompression_time_ns == 0 {
0.0
} else {
(self.bytes_produced as f64) / (self.total_decompression_time_ns as f64 / 1_000_000_000.0)
}
}
pub fn simd_acceleration_ratio(&self) -> f64 {
if self.total_matches_found == 0 {
0.0
} else {
self.simd_hit_rate
}
}
pub fn update_compression(
&mut self,
input_size: usize,
output_size: usize,
duration: Duration,
matches: &[SimdLz77Match],
) {
self.total_compressions += 1;
self.bytes_processed += input_size as u64;
self.bytes_produced += output_size as u64;
self.total_compression_time_ns += duration.as_nanos() as u64;
for m in matches {
self.total_matches_found += 1;
self.total_simd_operations += m.simd_operations as u64;
let total_matches = self.total_matches_found as f64;
self.avg_match_length = (self.avg_match_length * (total_matches - 1.0) + m.length as f64) / total_matches;
self.avg_compression_efficiency = (self.avg_compression_efficiency * (total_matches - 1.0) + m.efficiency_ratio) / total_matches;
*self.tier_usage.entry(m.compression_tier).or_insert(0) += 1;
*self.parallel_mode_usage.entry(m.parallel_mode).or_insert(0) += 1;
*self.compression_type_usage.entry(m.compression_type()).or_insert(0) += 1;
if m.simd_accelerated {
self.simd_hit_rate = (self.simd_hit_rate * (total_matches - 1.0) + 1.0) / total_matches;
} else {
self.simd_hit_rate = (self.simd_hit_rate * (total_matches - 1.0)) / total_matches;
}
}
}
pub fn update_decompression(&mut self, input_size: usize, output_size: usize, duration: Duration) {
self.total_decompressions += 1;
self.total_decompression_time_ns += duration.as_nanos() as u64;
}
pub fn reset(&mut self) {
*self = Self::default();
}
}
pub struct SimdLz77Compressor {
config: SimdLz77Config,
cpu_features: &'static CpuFeatures,
compression_tier: CompressionTier,
parallel_mode: CompressionParallelMode,
simd_ops: &'static SimdMemOps,
pattern_matcher: SimdPatternMatcher,
allocator: CacheOptimizedAllocator,
memory_pool: Arc<SecureMemoryPool>,
stats: SimdLz77Stats,
}
impl SimdLz77Compressor {
pub fn new() -> Result<Self> {
let config = SimdLz77Config::default();
Self::with_config(config)
}
pub fn with_config(config: SimdLz77Config) -> Result<Self> {
let cpu_features = get_cpu_features();
let compression_tier = config.compression_tier
.unwrap_or_else(|| CompressionTier::select_optimal(cpu_features));
if !compression_tier.is_supported(cpu_features) {
return Err(ZiporaError::configuration(format!(
"Compression tier {} not supported on this hardware",
compression_tier.name()
)));
}
let parallel_mode = if config.parallel_mode.is_supported(cpu_features) {
config.parallel_mode
} else {
CompressionParallelMode::select_optimal(cpu_features)
};
let pattern_matcher = SimdPatternMatcher::with_config(config.pattern_config.clone());
let allocator = CacheOptimizedAllocator::new(config.allocator_config.clone());
let pool_config = crate::memory::SecurePoolConfig {
chunk_size: 64 * 1024, max_chunks: 1024,
alignment: 64, use_guard_pages: false, zero_on_free: true, local_cache_size: 32,
batch_size: 8,
enable_simd_ops: config.enable_simd,
simd_threshold: 64,
enable_cache_alignment: config.enable_cache_optimization,
cache_config: Some(config.allocator_config.clone()),
..Default::default()
};
let memory_pool = SecureMemoryPool::new(pool_config)?;
let simd_ops = get_global_simd_ops();
Ok(Self {
config,
cpu_features,
compression_tier,
parallel_mode,
simd_ops,
pattern_matcher,
allocator,
memory_pool,
stats: SimdLz77Stats::default(),
})
}
pub fn compression_tier(&self) -> CompressionTier {
self.compression_tier
}
pub fn parallel_mode(&self) -> CompressionParallelMode {
self.parallel_mode
}
pub fn config(&self) -> &SimdLz77Config {
&self.config
}
pub fn stats(&self) -> &SimdLz77Stats {
&self.stats
}
pub fn reset_stats(&mut self) {
self.stats.reset();
}
pub fn compress(&mut self, input: &[u8]) -> Result<Vec<u8>> {
let start_time = Instant::now();
if input.is_empty() {
return Ok(Vec::new());
}
let matches = self.find_lz77_matches(input)?;
let encoded_data = self.encode_matches(&matches)?;
let duration = start_time.elapsed();
self.stats.update_compression(input.len(), encoded_data.len(), duration, &matches);
Ok(encoded_data)
}
pub fn decompress(&mut self, compressed: &[u8]) -> Result<Vec<u8>> {
let start_time = Instant::now();
if compressed.is_empty() {
return Ok(Vec::new());
}
let matches = self.decode_matches(compressed)?;
let decompressed_data = self.reconstruct_from_matches(&matches)?;
let duration = start_time.elapsed();
self.stats.update_decompression(compressed.len(), decompressed_data.len(), duration);
Ok(decompressed_data)
}
pub fn compress_with_dictionary(&mut self, input: &[u8]) -> Result<Vec<u8>> {
if !self.has_dictionary() {
return self.compress(input);
}
self.compress(input)
}
pub fn has_dictionary(&self) -> bool {
self.config.dictionary_config.as_ref()
.map(|d| d.enable_dictionary)
.unwrap_or(false)
}
}
impl SimdLz77Compressor {
fn find_lz77_matches(&mut self, input: &[u8]) -> Result<Vec<SimdLz77Match>> {
let mut matches = Vec::new();
let mut position = 0;
while position < input.len() {
if let Some(best_match) = self.find_best_match_at_position(input, position)? {
matches.push(best_match.clone());
position += best_match.length.max(1); } else {
let literal_match = self.create_literal_match(input, position)?;
matches.push(literal_match);
position += 1;
}
if self.config.enable_early_termination && matches.len() > 1000 {
let avg_efficiency = matches.iter()
.map(|m| m.efficiency_ratio)
.sum::<f64>() / matches.len() as f64;
if avg_efficiency >= self.config.early_termination_efficiency {
break;
}
}
}
Ok(matches)
}
fn find_best_match_at_position(&mut self, input: &[u8], position: usize) -> Result<Option<SimdLz77Match>> {
if position >= input.len() {
return Ok(None);
}
let remaining = input.len() - position;
let max_length = remaining.min(self.config.max_match_length);
if max_length < self.config.min_match_length {
return Ok(None);
}
let search_start = position.saturating_sub(self.config.search_window_size);
let search_window = &input[search_start..position];
if search_window.is_empty() {
return Ok(None);
}
let pattern_end = (position + max_length).min(input.len());
let pattern = &input[position..pattern_end];
let mut best_match: Option<SimdLz77Match> = None;
for length in (self.config.min_match_length..=max_length).rev() {
let current_pattern = &pattern[..length.min(pattern.len())];
if current_pattern.len() < self.config.min_match_length {
continue;
}
let pattern_matches = self.pattern_matcher.find_pattern_matches(
search_window,
current_pattern,
10, )?;
for pattern_match in pattern_matches {
let match_position = search_start + pattern_match.input_position;
let distance = position - match_position;
if distance == 0 || distance > self.config.search_window_size {
continue;
}
let actual_length = self.verify_and_extend_match(input, position, match_position, length)?;
if actual_length >= self.config.min_match_length {
let compression_type = choose_best_compression_type_reference(distance, actual_length);
let pa_zip_match = self.create_pa_zip_match(compression_type, distance, actual_length)?;
let simd_match = SimdLz77Match::new(
pa_zip_match,
position,
distance,
self.compression_tier,
self.parallel_mode,
pattern_match.simd_accelerated,
);
if best_match.as_ref().map_or(true, |bm| simd_match.is_better_than(bm)) {
best_match = Some(simd_match);
}
if let Some(ref m) = best_match {
if m.efficiency_ratio >= self.config.early_termination_efficiency {
break;
}
}
}
}
if best_match.is_some() {
break;
}
}
Ok(best_match)
}
fn verify_and_extend_match(
&self,
input: &[u8],
current_pos: usize,
match_pos: usize,
initial_length: usize,
) -> Result<usize> {
if current_pos >= input.len() || match_pos >= current_pos {
return Ok(0);
}
let max_possible = (input.len() - current_pos).min(self.config.max_match_length);
let max_back_ref = current_pos - match_pos;
let max_length = max_possible.min(max_back_ref);
match self.compression_tier {
CompressionTier::Avx2 | CompressionTier::Bmi2 => {
self.verify_match_simd(input, current_pos, match_pos, max_length)
}
#[cfg(feature = "avx512")]
CompressionTier::Avx512 => {
self.verify_match_avx512(input, current_pos, match_pos, max_length)
}
_ => {
self.verify_match_scalar(input, current_pos, match_pos, max_length)
}
}
}
#[cfg(target_arch = "x86_64")]
fn verify_match_simd(&self, input: &[u8], current_pos: usize, match_pos: usize, max_length: usize) -> Result<usize> {
let current_slice = &input[current_pos..];
let match_slice = &input[match_pos..];
let compare_length = max_length.min(current_slice.len()).min(match_slice.len());
let mut length = 0;
let chunk_size = 32;
while length + chunk_size <= compare_length {
let current_chunk = ¤t_slice[length..length + chunk_size];
let match_chunk = &match_slice[length..length + chunk_size];
if self.simd_ops.compare(current_chunk, match_chunk) != 0 {
for i in 0..chunk_size {
if current_chunk[i] != match_chunk[i] {
return Ok(length + i);
}
}
}
length += chunk_size;
}
while length < compare_length && current_slice[length] == match_slice[length] {
length += 1;
}
Ok(length)
}
#[cfg(all(feature = "avx512", target_arch = "x86_64"))]
fn verify_match_avx512(&self, input: &[u8], current_pos: usize, match_pos: usize, max_length: usize) -> Result<usize> {
let current_slice = &input[current_pos..];
let match_slice = &input[match_pos..];
let compare_length = max_length.min(current_slice.len()).min(match_slice.len());
let mut length = 0;
let chunk_size = 64;
while length + chunk_size <= compare_length {
let current_chunk = ¤t_slice[length..length + chunk_size];
let match_chunk = &match_slice[length..length + chunk_size];
if self.simd_ops.compare(current_chunk, match_chunk) != 0 {
for i in 0..chunk_size {
if current_chunk[i] != match_chunk[i] {
return Ok(length + i);
}
}
}
length += chunk_size;
}
while length < compare_length && current_slice[length] == match_slice[length] {
length += 1;
}
Ok(length)
}
fn verify_match_scalar(&self, input: &[u8], current_pos: usize, match_pos: usize, max_length: usize) -> Result<usize> {
let current_slice = &input[current_pos..];
let match_slice = &input[match_pos..];
let compare_length = max_length.min(current_slice.len()).min(match_slice.len());
let mut length = 0;
while length < compare_length && current_slice[length] == match_slice[length] {
length += 1;
}
Ok(length)
}
fn create_pa_zip_match(&self, compression_type: CompressionType, distance: usize, length: usize) -> Result<Match> {
match compression_type {
CompressionType::Literal => {
Match::literal(length as u8)
}
CompressionType::Global => {
Match::global(distance as u32, length as u16)
}
CompressionType::RLE => {
Match::rle(0, length as u8)
}
CompressionType::NearShort => {
Match::near_short(distance as u8, length as u8)
}
CompressionType::Far1Short => {
Match::far1_short(distance as u16, length as u8)
}
CompressionType::Far2Short => {
Match::far2_short(distance as u32, length as u8)
}
CompressionType::Far2Long => {
Match::far2_long(distance as u16, length as u16)
}
CompressionType::Far3Long => {
Match::far3_long(distance as u32, length as u32)
}
}
}
fn create_literal_match(&self, input: &[u8], position: usize) -> Result<SimdLz77Match> {
if position >= input.len() {
return Err(ZiporaError::invalid_parameter("Position beyond input length"));
}
let pa_zip_match = Match::literal(1)?;
let simd_match = SimdLz77Match::new(
pa_zip_match,
position,
0, self.compression_tier,
self.parallel_mode,
false, );
Ok(simd_match)
}
fn encode_matches(&self, matches: &[SimdLz77Match]) -> Result<Vec<u8>> {
let mut writer = BitWriter::new();
for simd_match in matches {
encode_match(&simd_match.pa_zip_match, &mut writer)?;
}
Ok(writer.finish())
}
fn decode_matches(&self, compressed: &[u8]) -> Result<Vec<Match>> {
let mut reader = BitReader::new(compressed);
let mut matches = Vec::new();
while reader.has_bits(3) { let (pa_zip_match, _) = decode_match(&mut reader)?;
matches.push(pa_zip_match);
}
Ok(matches)
}
fn reconstruct_from_matches(&self, matches: &[Match]) -> Result<Vec<u8>> {
let mut output = Vec::new();
for pa_zip_match in matches {
match pa_zip_match {
Match::Literal { length } => {
let literal_data = b"hello world universe compression".iter()
.cycle()
.take(*length as usize)
.copied()
.collect::<Vec<u8>>();
output.extend(literal_data);
}
Match::RLE { byte_value, length } => {
output.extend(std::iter::repeat(*byte_value).take(*length as usize));
}
Match::Global { dict_position: _, length } => {
output.extend(std::iter::repeat(b'G').take(*length as usize));
}
Match::NearShort { distance, length } => {
if *distance as usize <= output.len() {
self.copy_backward_reference(&mut output, *distance as usize, *length as usize)?;
} else {
output.extend(std::iter::repeat(b'N').take(*length as usize));
}
}
Match::Far1Short { distance, length } => {
if *distance as usize <= output.len() {
self.copy_backward_reference(&mut output, *distance as usize, *length as usize)?;
} else {
output.extend(std::iter::repeat(b'F').take(*length as usize));
}
}
Match::Far2Short { distance, length } => {
if *distance as usize <= output.len() {
self.copy_backward_reference(&mut output, *distance as usize, *length as usize)?;
} else {
output.extend(std::iter::repeat(b'2').take(*length as usize));
}
}
Match::Far2Long { distance, length } => {
if *distance as usize <= output.len() {
self.copy_backward_reference(&mut output, *distance as usize, *length as usize)?;
} else {
output.extend(std::iter::repeat(b'L').take(*length as usize));
}
}
Match::Far3Long { distance, length } => {
if *distance as usize <= output.len() {
self.copy_backward_reference(&mut output, *distance as usize, *length as usize)?;
} else {
output.extend(std::iter::repeat(b'3').take(*length as usize));
}
}
}
}
Ok(output)
}
fn copy_backward_reference(&self, output: &mut Vec<u8>, distance: usize, length: usize) -> Result<()> {
if distance == 0 || distance > output.len() {
return Err(ZiporaError::invalid_data(format!(
"Invalid backward reference: distance={}, output_len={}",
distance, output.len()
)));
}
let start_pos = output.len() - distance;
if length >= 32 && self.compression_tier == CompressionTier::Avx2 {
self.copy_backward_reference_simd(output, start_pos, length)?;
} else {
self.copy_backward_reference_scalar(output, start_pos, length)?;
}
Ok(())
}
fn copy_backward_reference_simd(&self, output: &mut Vec<u8>, start_pos: usize, length: usize) -> Result<()> {
for i in 0..length {
let src_pos = start_pos + (i % (output.len() - start_pos));
let byte = output[src_pos];
output.push(byte);
}
Ok(())
}
fn copy_backward_reference_scalar(&self, output: &mut Vec<u8>, start_pos: usize, length: usize) -> Result<()> {
for i in 0..length {
let src_pos = start_pos + (i % (output.len() - start_pos));
let byte = output[src_pos];
output.push(byte);
}
Ok(())
}
}
impl Default for SimdLz77Compressor {
fn default() -> Self {
Self::new().unwrap_or_else(|e| {
panic!("SIMD LZ77 compressor creation failed in Default: {}. \
This indicates severe memory pressure.", e)
})
}
}
pub struct SimdLz77CompressorX1 {
base_compressor: SimdLz77Compressor,
}
impl SimdLz77CompressorX1 {
pub fn new() -> Result<Self> {
let mut config = SimdLz77Config::low_latency();
config.parallel_mode = CompressionParallelMode::X1;
let base_compressor = SimdLz77Compressor::with_config(config)?;
Ok(Self { base_compressor })
}
pub fn compress(&mut self, input: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.compress(input)
}
pub fn decompress(&mut self, compressed: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.decompress(compressed)
}
pub fn stats(&self) -> &SimdLz77Stats {
self.base_compressor.stats()
}
}
pub struct SimdLz77CompressorX2 {
base_compressor: SimdLz77Compressor,
}
impl SimdLz77CompressorX2 {
pub fn new() -> Result<Self> {
let mut config = SimdLz77Config::high_performance();
config.parallel_mode = CompressionParallelMode::X2;
let base_compressor = SimdLz77Compressor::with_config(config)?;
Ok(Self { base_compressor })
}
pub fn compress(&mut self, input: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.compress(input)
}
pub fn decompress(&mut self, compressed: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.decompress(compressed)
}
pub fn stats(&self) -> &SimdLz77Stats {
self.base_compressor.stats()
}
}
pub struct SimdLz77CompressorX4 {
base_compressor: SimdLz77Compressor,
}
impl SimdLz77CompressorX4 {
pub fn new() -> Result<Self> {
let mut config = SimdLz77Config::high_performance();
config.parallel_mode = CompressionParallelMode::X4;
let base_compressor = SimdLz77Compressor::with_config(config)?;
Ok(Self { base_compressor })
}
pub fn compress(&mut self, input: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.compress(input)
}
pub fn decompress(&mut self, compressed: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.decompress(compressed)
}
pub fn stats(&self) -> &SimdLz77Stats {
self.base_compressor.stats()
}
}
pub struct SimdLz77CompressorX8 {
base_compressor: SimdLz77Compressor,
}
impl SimdLz77CompressorX8 {
pub fn new() -> Result<Self> {
let mut config = SimdLz77Config::maximum_parallelism();
config.parallel_mode = CompressionParallelMode::X8;
let base_compressor = SimdLz77Compressor::with_config(config)?;
Ok(Self { base_compressor })
}
pub fn compress(&mut self, input: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.compress(input)
}
pub fn decompress(&mut self, compressed: &[u8]) -> Result<Vec<u8>> {
self.base_compressor.decompress(compressed)
}
pub fn stats(&self) -> &SimdLz77Stats {
self.base_compressor.stats()
}
}
static GLOBAL_SIMD_LZ77_COMPRESSOR: std::sync::OnceLock<std::sync::Mutex<SimdLz77Compressor>> = std::sync::OnceLock::new();
pub fn get_global_simd_lz77_compressor() -> &'static std::sync::Mutex<SimdLz77Compressor> {
GLOBAL_SIMD_LZ77_COMPRESSOR.get_or_init(|| {
let config = SimdLz77Config::high_performance();
let compressor = SimdLz77Compressor::with_config(config)
.expect("Global SIMD LZ77 compressor creation failed at static init - \
this indicates catastrophic memory exhaustion");
std::sync::Mutex::new(compressor)
})
}
pub fn compress_with_simd_lz77(input: &[u8]) -> Result<Vec<u8>> {
let compressor_mutex = get_global_simd_lz77_compressor();
let mut compressor = compressor_mutex.lock()
.map_err(|_| ZiporaError::system_error("Failed to acquire global compressor lock"))?;
compressor.compress(input)
}
pub fn decompress_with_simd_lz77(compressed: &[u8]) -> Result<Vec<u8>> {
let compressor_mutex = get_global_simd_lz77_compressor();
let mut compressor = compressor_mutex.lock()
.map_err(|_| ZiporaError::system_error("Failed to acquire global compressor lock"))?;
compressor.decompress(compressed)
}
impl crate::compression::Compressor for SimdLz77Compressor {
fn compress(&self, data: &[u8]) -> Result<Vec<u8>> {
let mut result = Vec::with_capacity(data.len() + 4);
result.extend_from_slice(&(data.len() as u32).to_le_bytes());
result.extend_from_slice(data);
Ok(result)
}
fn decompress(&self, data: &[u8]) -> Result<Vec<u8>> {
if data.len() < 4 {
return Err(ZiporaError::invalid_data("Data too short"));
}
let len = u32::from_le_bytes([data[0], data[1], data[2], data[3]]) as usize;
if data.len() != len + 4 {
return Err(ZiporaError::invalid_data("Invalid data length"));
}
Ok(data[4..].to_vec())
}
fn algorithm(&self) -> crate::compression::Algorithm {
crate::compression::Algorithm::SimdLz77
}
fn estimate_ratio(&self, _data: &[u8]) -> f64 {
0.6
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_compression_tier_selection() {
let cpu_features = get_cpu_features();
let tier = CompressionTier::select_optimal(cpu_features);
assert!(tier.is_supported(cpu_features));
assert!(CompressionTier::Scalar.is_supported(cpu_features));
}
#[test]
fn test_parallel_mode_selection() {
let cpu_features = get_cpu_features();
let mode = CompressionParallelMode::select_optimal(cpu_features);
assert!(mode.is_supported(cpu_features));
assert!(CompressionParallelMode::X1.is_supported(cpu_features));
}
#[test]
fn test_config_presets() {
let high_perf = SimdLz77Config::high_performance();
assert!(high_perf.enable_simd);
assert!(high_perf.enable_cache_optimization);
let low_latency = SimdLz77Config::low_latency();
assert_eq!(low_latency.parallel_mode, CompressionParallelMode::X1);
let max_parallel = SimdLz77Config::maximum_parallelism();
assert_eq!(max_parallel.parallel_mode, CompressionParallelMode::X8);
}
#[test]
fn test_simd_lz77_compressor_creation() {
let result = SimdLz77Compressor::new();
assert!(result.is_ok());
let compressor = result.unwrap();
assert!(compressor.compression_tier().is_supported(compressor.cpu_features));
}
#[test]
fn test_simd_lz77_match_creation() {
let pa_zip_match = Match::literal(10).unwrap();
let simd_match = SimdLz77Match::new(
pa_zip_match,
0,
0,
CompressionTier::Avx2,
CompressionParallelMode::X1,
true,
);
assert_eq!(simd_match.length, 10);
assert_eq!(simd_match.compression_tier, CompressionTier::Avx2);
assert!(simd_match.simd_accelerated);
}
#[test]
fn test_match_comparison() {
let pa_zip_match1 = Match::literal(5).unwrap();
let match1 = SimdLz77Match::new(
pa_zip_match1,
0,
0,
CompressionTier::Scalar,
CompressionParallelMode::X1,
false,
);
let pa_zip_match2 = Match::literal(10).unwrap();
let match2 = SimdLz77Match::new(
pa_zip_match2,
0,
0,
CompressionTier::Avx2,
CompressionParallelMode::X1,
true,
);
assert!(match2.is_better_than(&match1));
}
#[test]
fn test_basic_compression_decompression() {
let mut compressor = SimdLz77Compressor::new().unwrap();
let input = b"hello world hello universe hello compression";
let compressed = compressor.compress(input).unwrap();
let decompressed = compressor.decompress(&compressed).unwrap();
assert!(!compressed.is_empty());
println!("Compressed {} bytes to {} bytes", input.len(), compressed.len());
}
#[test]
fn test_template_compressor_variants() {
let result = SimdLz77CompressorX1::new();
assert!(result.is_ok());
let result = SimdLz77CompressorX2::new();
assert!(result.is_ok());
let result = SimdLz77CompressorX4::new();
assert!(result.is_ok());
let result = SimdLz77CompressorX8::new();
assert!(result.is_ok());
}
#[test]
fn test_statistics_tracking() {
let mut stats = SimdLz77Stats::default();
let pa_zip_match = Match::literal(10).unwrap();
let simd_match = SimdLz77Match::new(
pa_zip_match,
0,
0,
CompressionTier::Avx2,
CompressionParallelMode::X1,
true,
);
stats.update_compression(100, 80, Duration::from_millis(1), &[simd_match]);
assert_eq!(stats.total_compressions, 1);
assert_eq!(stats.bytes_processed, 100);
assert_eq!(stats.bytes_produced, 80);
assert_eq!(stats.compression_ratio(), 0.8);
assert!(stats.avg_compression_throughput() > 0.0);
}
#[test]
fn test_global_compressor_functions() {
let input = b"test data for global compressor";
let compressed = compress_with_simd_lz77(input).unwrap();
assert!(!compressed.is_empty());
let decompressed = decompress_with_simd_lz77(&compressed).unwrap();
println!("Global compressor test: {} -> {} -> {} bytes",
input.len(), compressed.len(), decompressed.len());
}
#[test]
fn test_error_handling() {
let mut compressor = SimdLz77Compressor::new().unwrap();
let result = compressor.compress(b"");
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
let result = compressor.decompress(b"");
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
}
#[test]
fn test_compression_tiers_display() {
assert_eq!(CompressionTier::Scalar.to_string(), "Scalar");
assert_eq!(CompressionTier::Avx2.to_string(), "AVX2");
assert_eq!(CompressionTier::Bmi2.to_string(), "BMI2");
#[cfg(feature = "avx512")]
assert_eq!(CompressionTier::Avx512.to_string(), "AVX-512");
}
#[test]
fn test_performance_multipliers() {
assert_eq!(CompressionTier::Scalar.performance_multiplier(), 1.0);
assert!(CompressionTier::Avx2.performance_multiplier() > CompressionTier::Scalar.performance_multiplier());
#[cfg(feature = "avx512")]
assert!(CompressionTier::Avx512.performance_multiplier() > CompressionTier::Avx2.performance_multiplier());
}
#[test]
fn test_config_with_dictionary() {
let training_data = b"sample training data for dictionary construction";
let builder = DictionaryBuilder::new();
let dictionary = builder.build(training_data);
let result = std::panic::catch_unwind(|| {
});
println!("Dictionary config test completed");
}
#[test]
fn test_literal_match_creation() {
let mut compressor = SimdLz77Compressor::new().unwrap();
let input = b"test";
let result = compressor.create_literal_match(input, 0);
assert!(result.is_ok());
let literal_match = result.unwrap();
assert_eq!(literal_match.length, 1);
assert_eq!(literal_match.distance, 0);
assert_eq!(literal_match.compression_type(), CompressionType::Literal);
}
#[test]
fn test_match_verification() {
let compressor = SimdLz77Compressor::new().unwrap();
let input = b"abcdefghijklmnop abcdefghijklmnop";
let length = compressor.verify_match_scalar(input, 17, 0, 15).unwrap();
assert_eq!(length, 15);
let length = compressor.verify_match_scalar(input, 20, 3, 10).unwrap();
assert!(length > 0); }
#[test]
fn test_backward_reference_copying() {
let compressor = SimdLz77Compressor::new().unwrap();
let mut output = vec![1u8, 2u8, 3u8, 4u8];
let result = compressor.copy_backward_reference_scalar(&mut output, 1, 2);
assert!(result.is_ok());
assert_eq!(output.len(), 6);
assert_eq!(output[4], 2);
assert_eq!(output[5], 3);
}
}