Rust如何高效读写~100M结构体至磁盘?附zstd压缩示例
使用rkyv搭配zstd处理大规模结构体序列化/反序列化
针对1亿级结构体的序列化需求,推荐用rkyv搭配zstd:rkyv是零拷贝高性能序列化库,无需运行时反射,序列化/反序列化速度极快;zstd则能在压缩速度和体积间取得极佳平衡,非常适合大规模数据场景。
依赖配置
在Cargo.toml中添加所需依赖:
[dependencies] rkyv = { version = "0.7", features = ["std"] } zstd = { version = "0.12", features = ["std"] }
定义支持序列化的结构体
为结构体派生rkyv的Archive、Serialize和Deserialize trait,优先使用固定长度类型以提升性能和压缩率:
use rkyv::{Archive, Deserialize, Serialize}; #[derive(Archive, Deserialize, Serialize, Debug)] #[archive(check_bytes)] // 可选,用于反序列化时校验数据完整性 struct MyData { id: u32, value: f64, flag: bool, name: [u8; 16], // 固定长度数组比String更适合高性能场景 }
序列化+压缩写入文件
先通过rkyv序列化数据,再用zstd压缩后写入文件:
use std::fs::File; use std::io::BufWriter; use std::io::Write; use zstd::bulk::compress; fn serialize_and_compress(data: &[MyData], output_path: &str) -> Result<(), Box<dyn std::error::Error>> { // 1. rkyv序列化,直接生成字节切片 let serialized = rkyv::to_bytes::<_, 0>(data)?; // 2. zstd压缩:级别6是速度/体积的平衡点,追求速度选1-3,追求体积选7-10 let compressed = compress(serialized.as_slice(), 6)?; // 3. 用BufWriter提升大文件写入效率 let mut file = BufWriter::new(File::create(output_path)?); file.write_all(&compressed)?; Ok(()) }
读取压缩文件+反序列化
读取压缩数据后解压,再通过rkyv反序列化回结构体Vec:
use std::fs::read; use zstd::bulk::decompress; fn decompress_and_deserialize(input_path: &str) -> Result<Vec<MyData>, Box<dyn std::error::Error>> { // 1. 读取压缩文件内容 let compressed = read(input_path)?; // 2. 获取解压后的最大可能尺寸,执行zstd解压 let decompress_bound = zstd::bulk::decompress_bound(&compressed)?; let decompressed = decompress(&compressed, decompress_bound)?; // 3. rkyv反序列化:若仅需只读访问,可直接使用`archived`(零拷贝,速度最快) let archived = rkyv::from_bytes::<Vec<MyData>>(&decompressed)?; // 若需要修改数据,再反序列化为可编辑实例 let data = archived.deserialize(&mut rkyv::Infallible)?; Ok(data) }
额外优化建议
- 结构体字段优先用固定长度类型,避免动态内存分配,减少序列化体积和耗时
- 超大规模数据可分块处理,避免一次性占用过多内存
- 读写文件始终使用
BufWriter/BufReader,减少系统调用次数提升IO效率
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

