use ipfrs_tensorlogic::{
AdaptiveBuffer, BufferPool, StackBuffer, TypedBufferPool, ZeroCopyConverter,
};
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Allocation Optimization Example ===\n");
println!("--- Buffer Pool ---");
let pool = BufferPool::new(4096, 10); println!("Created buffer pool: 4KB buffers, max 10 pooled");
let start = Instant::now();
for i in 0..100 {
let mut buffer = pool.acquire();
buffer.as_mut().extend_from_slice(&[i as u8; 100]);
}
let pool_duration = start.elapsed();
println!("100 pooled allocations: {:?}", pool_duration);
println!("Pool size after: {}", pool.size());
let start = Instant::now();
for i in 0..100 {
let mut buffer = Vec::with_capacity(4096);
buffer.extend_from_slice(&[i as u8; 100]);
}
let direct_duration = start.elapsed();
println!("100 direct allocations: {:?}", direct_duration);
println!(
"Speedup: {:.2}x\n",
direct_duration.as_nanos() as f64 / pool_duration.as_nanos() as f64
);
println!("--- Typed Buffer Pool ---");
let float_pool = TypedBufferPool::<f32>::new(1024, 10);
println!("Created typed buffer pool for f32");
let mut buffer = float_pool.acquire();
buffer.extend((0..100).map(|i| i as f32));
println!("Buffer length: {}", buffer.len());
println!("Sum: {}", buffer.iter().sum::<f32>());
drop(buffer);
println!("Pool size: {}\n", float_pool.size());
println!("--- Stack Buffer ---");
let mut stack_buf = StackBuffer::<256>::new();
println!(
"Created stack buffer: {} bytes capacity",
stack_buf.capacity()
);
stack_buf.write(b"Hello, ")?;
stack_buf.write(b"World!")?;
println!("Written: {:?}", std::str::from_utf8(stack_buf.as_slice())?);
println!(
"Length: {}, Remaining: {}",
stack_buf.len(),
stack_buf.remaining()
);
let large_data = vec![0u8; 300];
match stack_buf.write(&large_data) {
Ok(_) => println!("Should not reach here"),
Err(e) => println!("Overflow prevented: {}\n", e),
}
println!("--- Adaptive Buffer ---");
let mut adaptive_small = AdaptiveBuffer::new(10);
adaptive_small.write(b"small")?;
println!(
"Small buffer (hint=10): {} bytes, still on stack",
adaptive_small.len()
);
let mut adaptive_large = AdaptiveBuffer::new(1000);
adaptive_large.write(&vec![0u8; 500])?;
println!(
"Large buffer (hint=1000): {} bytes, using heap",
adaptive_large.len()
);
let mut adaptive_upgrade = AdaptiveBuffer::new(10);
adaptive_upgrade.write(&[0u8; 100])?; adaptive_upgrade.write(&[0u8; 200])?; println!(
"Auto-upgraded buffer: {} bytes (started on stack, upgraded to heap)\n",
adaptive_upgrade.len()
);
println!("--- Zero-Copy Conversions ---");
let floats: Vec<f32> = (0..1000).map(|i| i as f32).collect();
println!(
"Original floats: {} elements, {} bytes",
floats.len(),
floats.len() * 4
);
let start = Instant::now();
let bytes = ZeroCopyConverter::slice_to_bytes(&floats);
let zero_copy_duration = start.elapsed();
println!(
"Zero-copy to bytes: {} bytes in {:?}",
bytes.len(),
zero_copy_duration
);
let start = Instant::now();
let copied_bytes: Vec<u8> = floats.iter().flat_map(|f| f.to_le_bytes()).collect();
let copy_duration = start.elapsed();
println!(
"Copying to bytes: {} bytes in {:?}",
copied_bytes.len(),
copy_duration
);
println!(
"Speedup: {:.2}x",
copy_duration.as_nanos() as f64 / zero_copy_duration.as_nanos() as f64
);
let floats_back: &[f32] = ZeroCopyConverter::bytes_to_slice(bytes);
println!("Zero-copy back: {} elements", floats_back.len());
println!("Data integrity: {}\n", floats == floats_back);
println!("--- Batch Processing with Pool ---");
let processing_pool = BufferPool::new(8192, 8);
let num_batches = 10;
println!("Processing {} batches with pooled buffers...", num_batches);
let start = Instant::now();
for batch_id in 0..num_batches {
let mut buffer = processing_pool.acquire();
for i in 0..100 {
let data = format!("batch_{}_item_{}", batch_id, i);
buffer.as_mut().extend_from_slice(data.as_bytes());
}
let _ = buffer.len();
}
let total_duration = start.elapsed();
println!("Processed {} batches in {:?}", num_batches, total_duration);
println!("Average per batch: {:?}", total_duration / num_batches);
println!(
"Final pool size: {} (buffers available for reuse)",
processing_pool.size()
);
println!("\n--- Summary ---");
println!("✓ Buffer pooling reduces allocation overhead");
println!("✓ Stack buffers avoid heap allocation for small data");
println!("✓ Adaptive buffers automatically choose stack or heap");
println!("✓ Zero-copy conversions eliminate unnecessary copying");
println!("✓ Typed pools provide type-safe buffer reuse");
println!("\n✓ Example completed successfully!");
Ok(())
}