Rust高效内存压缩库packedvec使用指南
概述
packedvec是一个高效的Rust内存压缩库,专门用于实现紧凑的动态数组存储。它通过位压缩技术优化内存使用,特别适合存储大量小数值或布尔值等数据。
主要特性
- 内存高效的动态数组实现
- 支持多种整数类型(u8, u16, u32, u64)
- 自动位压缩存储
- 零成本抽象(编译时优化)
- 安全的Rust API
安装方法
在Cargo.toml中添加依赖:
[dependencies]
packedvec = "0.3"
基本用法
创建压缩数组
use packedvec::PackedVec;
fn main() {
// 创建包含小数值的压缩数组
let mut vec = PackedVec::new();
vec.push(5u8);
vec.push(10u8);
vec.push(15u8);
println!("数组长度: {}", vec.len());
println!("内存使用量: {} 字节", vec.memory_usage());
}
批量初始化
use packedvec::PackedVec;
fn main() {
// 从现有数据创建压缩数组
let data = vec![1u32, 2, 3, 4, 5, 1000];
let packed = PackedVec::from_vec(data);
// 访问元素
println!("第三个元素: {}", packed.get(2).unwrap());
println!("内存节省: {}%", calculate_savings(&packed));
}
fn calculate_savings(packed: &PackedVec<u32>) -> f32 {
let normal_size = packed.len() * std::mem::size_of::<u32>();
let packed_size = packed.memory_usage();
(1.0 - packed_size as f32 / normal_size as f32) * 100.0
}
迭代操作
use packedvec::PackedVec;
fn main() {
let mut packed = PackedVec::new();
for i in 0..1000 {
packed.push(i as u16 % 100); // 数值范围小,压缩效果好
}
// 迭代访问
for (index, &value) in packed.iter().enumerate() {
if index % 100 == 0 {
println!("索引 {}: 值 {}", index, value);
}
}
// 使用map转换
let doubled: Vec<u32> = packed.iter().map(|&x| x as u32 * 2).collect();
}
布尔值压缩存储
use packedvec::PackedVec;
fn main() {
// 特别适合存储布尔值(每个值只需1位)
let mut flags = PackedVec::new();
// 添加1000个布尔值
for i in 0..1000 {
flags.push(i % 2 == 0);
}
println!("布尔数组内存使用: {} 字节", flags.memory_usage());
println!("传统Vec<bool>需要: {} 字节", 1000 / 8);
// 统计真值数量
let true_count = flags.iter().filter(|&&b| b).count();
println!("真值数量: {}", true_count);
}
完整示例demo
use packedvec::PackedVec;
fn main() {
// 示例1:基本使用
println!("=== 基本使用示例 ===");
let mut packed_vec = PackedVec::new();
// 添加小范围数值
for i in 0..50 {
packed_vec.push(i as u8); // 数值范围0-49,压缩效果好
}
println!("数组长度: {}", packed_vec.len());
println!("内存使用量: {} 字节", packed_vec.memory_usage());
println!("传统Vec<u8>需要: {} 字节", packed_vec.len() * std::mem::size_of::<u8>());
// 示例2:批量操作
println!("\n=== 批量操作示例 ===");
let data: Vec<u32> = (0..1000).map(|x| x % 256).collect(); // 数值范围0-255
let packed_batch = PackedVec::from_vec(data.clone());
println!("批量创建数组长度: {}", packed_batch.len());
println!("批量创建内存使用: {} 字节", packed_batch.memory_usage());
println!("内存节省率: {:.2}%",
(1.0 - packed_batch.memory_usage() as f32 / (packed_batch.len() * 4) as f32) * 100.0);
// 示例3:布尔值存储
println!("\n=== 布尔值存储示例 ===");
let mut bool_vec = PackedVec::new();
// 存储10000个布尔值
for i in 0..10000 {
bool_vec.push(i % 3 == 0); // 每3个元素一个true
}
println!("布尔数组长度: {}", bool_vec.len());
println!("布尔数组内存: {} 字节", bool_vec.memory_usage());
println!("理想压缩大小: {} 字节", bool_vec.len() / 8);
// 统计true的数量
let true_count = bool_vec.iter().filter(|&&b| b).count();
println!("True数量: {} ({:.1}%)", true_count, true_count as f32 / bool_vec.len() as f32 * 100.0);
// 示例4:性能对比
println!("\n=== 性能对比示例 ===");
compare_performance();
}
fn compare_performance() {
use std::time::Instant;
// 测试数据
let test_data: Vec<u16> = (0..100000).map(|x| x % 100).collect(); // 小范围数值
// 标准Vec性能测试
let start = Instant::now();
let normal_vec: Vec<u16> = test_data.iter().cloned().collect();
let normal_time = start.elapsed();
// PackedVec性能测试
let start = Instant::now();
let packed_vec = PackedVec::from_vec(test_data.clone());
let packed_time = start.elapsed();
println!("标准Vec创建时间: {:?}", normal_time);
println!("PackedVec创建时间: {:?}", packed_time);
println!("PackedVec内存节省: {:.1}%",
(1.0 - packed_vec.memory_usage() as f32 / (normal_vec.len() * 2) as f32) * 100.0);
}
性能提示
- 对于小范围数值(如0-255),packedvec能提供最佳压缩效果
- 批量操作比单个操作更高效
- 考虑数据访问模式,随机访问可能比顺序访问稍慢
适用场景
- 大规模布尔值存储
- 枚举值存储
- 小范围整数值集合
- 内存敏感的应用场景
- 需要序列化/反序列化大量数据的场景
注意事项
- 压缩和解压缩需要额外的CPU开销
- 不适合存储大范围或浮点数值
- 随机访问性能略低于标准Vec
packedvec在需要优化内存使用的场景中表现出色,特别是在处理大量小数值数据时能够显著减少内存占用。