You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中如何结合BufReader使用bincode::deserialize_from加速大文件读取

问题场景
  • 以下为演示用示例代码,实际业务场景需要处理以相同写入方式生成的超大型二进制文件
  • 待读取的超大二进制文件均为自行通过bincode序列化写入
  • 核心目标:通过Bincode生成大体积序列化文件,后续可迭代遍历文件内存储的结构化数据

原有演示代码如下:

#[macro_use]
extern crate serde;
extern crate bincode;

// use std::fs::File;
use bincode::serialize_into;
use std::io::BufWriter;

#[derive(Serialize, Deserialize, PartialEq, Debug)]
pub struct MyStruct {
    counter: Vec<u32>,
    offset: usize,
}

impl MyStruct {
    // 省略其他逻辑
    pub fn new(counter: Vec<u32>, offset: usize) -> Self {
        Self { counter, offset }
    }
}
fn main() {
    let mut vec = Vec::new();
    vec.push(100);
    vec.push(500);
    vec.push(100);
    vec.push(500);
    vec.push(100);
    vec.push(500);
    let m = MyStruct::new(vec, 0);

    // 填充counter向量内容

    let mut f = BufWriter::new(File::create("foo2.bar").unwrap());
    serialize_into(&mut f, &m).unwrap();
    let mut vec = Vec::new();
    vec.push(100);
    vec.push(600);
    vec.push(100);
    vec.push(500);
    vec.push(100);
    vec.push(600);
    vec.push(500);
    vec.push(101241241);
    vec.push(600);
    let m2 = MyStruct::new(vec, 35);
    serialize_into(&mut f, &m2).unwrap();
    drop(f);
    
    let input = File::open("foo2.bar").unwrap();
    // let buffered = BufReader::new(input);
    let mut vecs: Vec<MyStruct> = Vec::new();
    loop {
        match bincode::deserialize_from(&input) {
            Ok(file) => vecs.push(file),
            Err(error) => break,
        };
    }
}

当前实现直接对原始File句柄执行读取,IO效率极低导致运行速度很慢。已经编写了包裹File实例的BufReader初始化代码,需要修改逻辑让bincode::deserialize_from使用BufReader提升读取性能,已完成的初始化代码如下:

let input = File::open("foo2.bar").unwrap();
let buffered = BufReader::new(input);
修改方法

bincode::deserialize_from的参数只要求实现std::io::Read trait,BufReader本身就实现了该trait,只需要注意两个细节即可直接使用:

  1. BufReader实例必须声明为可变(mut),因为反序列化读取过程会修改其内部缓冲区和读取游标
  2. 传入deserialize_from时传BufReader的可变引用,不要按值传入,否则第一次反序列化会拿走BufReader的所有权,后续循环无法继续读取剩余内容

完整修改步骤

  1. 提前引入BufReader:
    use std::io::BufReader;
    
  2. 将原有读取逻辑替换为以下代码:
    let input = File::open("foo2.bar").unwrap();
    let mut buffered = BufReader::new(input);
    let mut vecs: Vec<MyStruct> = Vec::new();
    loop {
        match bincode::deserialize_from(&mut buffered) {
            Ok(file) => vecs.push(file),
            Err(e) => {
                // 生产环境建议区分错误类型:仅遇到文件末尾错误时正常退出,其他错误抛出处理
                break
            }
        };
    }
    

注意事项

  • 示例中遇到错误直接break的写法仅适用于演示,实际业务场景需要判断错误类型:如果是IO错误且错误kind为UnexpectedEof才代表文件正常读取完毕,其余错误(比如序列化格式损坏、IO异常)需要单独处理,避免静默失败。
  • 对于GB级以上的超大文件,还可以根据磁盘页大小调整BufReader的缓冲区容量(通过BufReader::with_capacity初始化),进一步减少系统调用次数提升性能。

内容的提问来源于stack exchange,提问作者tradinggy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:39:15