#![allow(clippy::result_large_err)]
use numrs2::array::Array;
use numrs2::error::Result;
use numrs2::memory_alloc::{
get_global_memory_stats, get_global_spill_stats, init_global_manager, should_spill_globally,
CacheStrategy, LargeScaleConfig, OutOfCoreArray, OutOfCoreConfig,
};
fn main() -> Result<()> {
println!("NumRS2 Large-Scale Memory Management Example");
println!("============================================\n");
example_large_scale_manager()?;
example_out_of_core_arrays()?;
example_memory_monitoring()?;
example_data_spilling()?;
println!("\nAll large-scale memory management examples completed successfully!");
Ok(())
}
fn example_large_scale_manager() -> Result<()> {
println!("1. Large-Scale Memory Manager");
println!("----------------------------");
let config = LargeScaleConfig {
max_memory_usage: 100 * 1024 * 1024, spill_threshold: 0.7, chunk_size: 1024 * 1024, temp_dir: std::env::temp_dir().join("numrs_large_scale_example"),
background_cleanup: true,
monitor_interval_ms: 500,
enable_stats: true,
};
init_global_manager(config)?;
println!("✓ Large-scale memory manager initialized");
println!(" - Memory limit: 100MB");
println!(" - Spill threshold: 70%");
println!(" - Chunk size: 1MB");
let _large_data = vec![1.0f64; 50_000_000];
if should_spill_globally() {
println!(" - Spilling is recommended");
}
println!();
Ok(())
}
fn example_out_of_core_arrays() -> Result<()> {
println!("2. Out-of-Core Arrays");
println!("--------------------");
let config = OutOfCoreConfig {
max_chunks_in_memory: 4, chunk_size: 10_000, storage_path: std::env::temp_dir().join("numrs_ooc_example"),
use_compression: false,
cache_strategy: CacheStrategy::LRU,
enable_prefetch: true,
prefetch_count: 2,
};
let data_size = 100_000; let data: Vec<f64> = (0..data_size).map(|i| i as f64 * 0.5).collect();
let shape = vec![data_size];
println!("✓ Creating out-of-core array with {} elements", data_size);
let mut ooc_array = OutOfCoreArray::from_data(data, shape, config)?;
println!(" - Accessing elements across different chunks...");
let test_indices = [1000, 25000, 50000, 75000, 99000];
for &index in &test_indices {
let value = ooc_array.get(&[index])?;
println!(" Element [{}] = {:.1}", index, value);
}
println!(" - Modifying elements...");
ooc_array.set(&[5000], 42.0)?;
ooc_array.set(&[30000], 84.0)?;
let modified_1 = ooc_array.get(&[5000])?;
let modified_2 = ooc_array.get(&[30000])?;
println!(" Modified [5000] = {:.1}", modified_1);
println!(" Modified [30000] = {:.1}", modified_2);
let cache_stats = ooc_array.get_cache_stats();
println!(" - Cache statistics:");
println!(" Total chunks: {}", cache_stats.total_chunks);
println!(" Chunks in memory: {}", cache_stats.chunks_in_memory);
println!(" Chunks on disk: {}", cache_stats.chunks_on_disk);
println!(" Dirty chunks: {}", cache_stats.dirty_chunks);
println!(" Cache limit: {}", cache_stats.cache_limit);
ooc_array.sync_all()?;
println!(" ✓ All changes synced to disk");
println!();
Ok(())
}
fn example_memory_monitoring() -> Result<()> {
println!("3. Memory Usage Monitoring");
println!("-------------------------");
let initial_stats = get_global_memory_stats()?;
println!("✓ Initial memory statistics:");
println!(" - Current usage: {} bytes", initial_stats.current_usage);
println!(" - Peak usage: {} bytes", initial_stats.peak_usage);
println!(
" - Active allocations: {}",
initial_stats.active_allocations
);
println!(" - Total allocations: {}", initial_stats.total_allocations);
let arrays: Vec<Array<f64>> = (0..5)
.map(|i| {
let size = (i + 1) * 10_000;
let data: Vec<f64> = (0..size).map(|x| x as f64).collect();
Array::from_vec(data)
})
.collect();
println!(" - Created {} arrays with varying sizes", arrays.len());
let updated_stats = get_global_memory_stats()?;
println!(" ✓ Updated memory statistics:");
println!(" Current usage: {} bytes", updated_stats.current_usage);
println!(" Peak usage: {} bytes", updated_stats.peak_usage);
println!(
" Active allocations: {}",
updated_stats.active_allocations
);
let usage_increase = updated_stats
.current_usage
.saturating_sub(initial_stats.current_usage);
println!(" Memory usage increase: {} bytes", usage_increase);
println!();
Ok(())
}
fn example_data_spilling() -> Result<()> {
println!("4. Data Spilling");
println!("---------------");
let initial_spill_stats = get_global_spill_stats()?;
println!("✓ Initial spill statistics:");
println!(
" - Total spilled size: {} bytes",
initial_spill_stats.total_spilled_size
);
println!(
" - Spilled data count: {}",
initial_spill_stats.spilled_count
);
println!(
" - Temp directory: {}",
initial_spill_stats.temp_dir.display()
);
let large_dataset_size = 1_000_000;
let large_dataset: Vec<f64> = (0..large_dataset_size).map(|i| (i as f64).sin()).collect();
println!(
" - Created large dataset with {} elements",
large_dataset_size
);
let chunk_size = 50_000;
let mut sum = 0.0;
let mut processed_elements = 0;
println!(
" - Processing dataset in chunks of {} elements...",
chunk_size
);
for chunk in large_dataset.chunks(chunk_size) {
let chunk_sum: f64 = chunk.iter().sum();
sum += chunk_sum;
processed_elements += chunk.len();
if processed_elements % (chunk_size * 4) == 0 && should_spill_globally() {
println!(" Warning: Memory usage high, spilling recommended");
}
}
println!(" ✓ Processed {} elements", processed_elements);
println!(" Total sum: {:.2}", sum);
println!(" Average: {:.6}", sum / processed_elements as f64);
println!(" - Using chunked iterator for memory-efficient processing...");
let test_array = Array::from_vec((0..100_000).map(|i| i as f32).collect());
let mut chunk_count = 0;
let mut total_processed = 0;
for i in (0..test_array.len()).step_by(10_000) {
let end = std::cmp::min(i + 10_000, test_array.len());
let chunk_size = end - i;
chunk_count += 1;
total_processed += chunk_size;
if chunk_count <= 3 {
println!(
" Chunk {}: {} elements (indices {}-{})",
chunk_count,
chunk_size,
i,
end - 1
);
}
}
if chunk_count > 3 {
println!(" ... and {} more chunks", chunk_count - 3);
}
println!(
" ✓ Processed {} elements in {} chunks",
total_processed, chunk_count
);
let final_spill_stats = get_global_spill_stats()?;
println!(" ✓ Final spill statistics:");
println!(
" Total spilled size: {} bytes",
final_spill_stats.total_spilled_size
);
println!(
" Spilled data count: {}",
final_spill_stats.spilled_count
);
println!();
Ok(())
}