Rust容量构建器库capacity_builder的使用,高效内存管理与动态容量调整工具

capacity_builder

构建器,其中计算容量的代码与编写构建内容的代码相同。

概述

有时您有一些复杂的代码,计算其容量可能会有点麻烦,或者容易与实现不同步。这个 crate 使得保持同步更容易,因为它是相同的代码。

StringBuilder

use capacity_builder::StringBuilder;

let text = StringBuilder::<String>::build(|builder| {
  for (i, import_module) in import_modules.iter().enumerate() {
    builder.append("// "); // 添加注释前缀
    builder.append(i); // 添加索引
    builder.append(" import\n"); // 添加导入文本
    builder.append("import \""); // 添加导入语句开始
    builder.append(import_module); // 添加模块名
    builder.append("\";\n"); // 添加导入语句结束
  }
})?;

在幕后,它运行闭包一次来计算容量,第二次来写入字符串。

注意,提供一个拥有的值会在编译时导致错误,以防止进行两次分配而不是一次:

let text = StringBuilder::<String>::build(|builder| {
  builder.append("some allocated value".to_string());
                 ^-- 生命周期编译时错误
})?;

要修复这个问题,在闭包外部分配:

let value = "some allocated value".to_string();
let text = StringBuilder::<String>::build(|builder| {
  builder.append(&value); // 正确
})?;

BytesBuilder

字节构建器类似于 StringBuilder

use capacity_builder::BytesBuilder;

let bytes = BytesBuilder::<Vec<u8>>::build(|builder| {
  builder.append_le(123); // 以小端字节序添加数字
  builder.append("example"); // 添加字符串
  builder.append(other_bytes); // 添加其他字节
})?;

使对象可附加

自定义类型可以通过实现 BytesAppendableStringAppendable 特征附加到构建器。

例如:

use capacity_builder::BytesAppendable;
use capacity_builder::BytesBuilder;
use capacity_builder::BytesType;

struct MyStruct;

impl<'a> BytesAppendable<'a> for &'a MyStruct {
  fn append_to_builder<TBytes: BytesType>(self, builder: &mut BytesBuilder<'a, TBytes>) {
    builder.append("Hello"); // 添加 Hello
    builder.append(" there!"); // 添加 there!
  }
}

let bytes = BytesBuilder::<Vec<u8>>::build(|builder| {
  builder.append(&MyStruct); // 工作
})
.unwrap();
assert_eq!(bytes, b"Hello there!"); // 断言字节内容

或使用字符串:

use capacity_builder::StringAppendable;
use capacity_builder::StringBuilder;
use capacity_builder::StringType;

#[derive(Debug)]
pub struct Version {
  // ...
}

impl<'a> StringAppendable for &'a Version {
  fn append_to_builder<TString: StringType>(
    &'a self,
    builder: &mut StringBuilder<'a, TString>,
  ) {
    builder.append(version.major); // 添加主版本号
    builder.append('.'); // 添加点号
    builder.append(version.minor); // 添加次版本号
    builder.append('.'); // 添加点号
    builder.append(version.patch); // 添加修订号
    if !version.pre.is_empty() { // 如果有预发布版本
      builder.append('-'); // 添加连字符
      for (i, part) in version.pre.iter().enumerate() { // 遍历预发布部分
        if i > 0 {
          builder.append('.'); // 添加点号分隔符
        }
        builder.append(part); // 添加部分
      }
    }
    if !version.build.is_empty() { // 如果有构建元数据
      builder.append('+'); // 添加加号
      for (i, part) in version.build.iter().enumerate() { // 遍历构建部分
        if i > 0 {
          builder.append('.'); // 添加点号分隔符
        }
        builder.append(part); // 添加部分
      }
    }
  }
}

实现更快的 .to_string()std::fmt::Display

默认的 .to_string() 实现重用了 std::fmt::Display。这很慢,因为没有设置容量。

这个 crate 提供了一个 #[derive(CapacityDisplay)] 宏,用于实现 .to_string()std::fmt::Display,重用 StringAppendable 中的实现。

use capacity_builder::CapacityDisplay;
use capacity_builder::StringAppendable;

#[derive(CapacityDisplay)] // <-- 添加这个
pub struct Version {
  // ...
}

impl<'a> StringAppendable for &'a Version {
  // ...参见上面的示例实现
}

现在 version.to_string() 将很快并返回一个具有准确容量的字符串。此外,您可以在格式字符串中使用结构体,这会回退到只是写入格式化器,其性能应与以前大致相同。

附注:您可能已经注意到构建器似乎没有暴露格式错误。这是因为格式化时的错误非常罕见,如果遇到错误,它将存储错误以在最后显示,其余的 append 语句停止格式化。

Cargo 特性

  • ecow
  • hipstr

示例:

# Cargo.toml
capacity_builder = { version = "...", features = ["ecow"] }
let text = StringBuilder::<ecow::EcoString>::build(|builder| {
  // ...
}).unwrap();

提示

  • 在运行闭包之前进行任何必要的分配。
  • 在使用此 crate 之前和之后进行测量,以确保您不会变慢。

完整示例代码

基于内容提供的示例,以下是完整的演示代码:

use capacity_builder::StringBuilder;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例1: 基本StringBuilder使用
    let import_modules = vec!["module1", "module2", "module3"];
    let text = StringBuilder::<String>::build(|builder| {
        for (i, import_module) in import_modules.iter().enumerate() {
            builder.append("// ");
            builder.append(i);
            builder.append(" import\n");
            builder.append("import \"");
            builder.append(import_module);
            builder.append("\";\n");
        }
    })?;
    
    println!("Generated text:\n{}", text);

    // 示例2: 避免闭包内分配
    let value = "some allocated value".to_string();
    let text2 = StringBuilder::<String>::build(|builder| {
        builder.append(&value);
    })?;
    
    println!("Text with external allocation: {}", text2);

    Ok(())
}
use capacity_builder::BytesBuilder;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // BytesBuilder示例
    let other_bytes = b"other bytes";
    let bytes = BytesBuilder::<Vec<u8>>::build(|builder| {
        builder.append_le(123u32); // 添加32位小端整数
        builder.append("example"); // 添加字符串
        builder.append(other_bytes); // 添加字节切片
    })?;
    
    println!("Generated bytes: {:?}", bytes);
    Ok(())
}
use capacity_builder::{BytesAppendable, BytesBuilder, BytesType};

// 自定义结构体实现BytesAppendable
struct MyStruct;

impl<'a> BytesAppendable<'a> for &'a MyStruct {
    fn append_to_builder<TBytes: BytesType>(self, builder: &mut BytesBuilder<'a, TBytes>) {
        builder.append("Hello");
        builder.append(" there!");
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bytes = BytesBuilder::<Vec<u8>>::build(|builder| {
        builder.append(&MyStruct);
    })?;
    
    assert_eq!(bytes, b"Hello there!");
    println!("Custom struct bytes: {:?}", bytes);
    Ok(())
}

1 回复

Rust容量构建器库capacity_builder的使用指南

库简介

capacity_builder是一个专为Rust设计的高效内存管理与动态容量调整工具。它提供了智能的容量管理策略,帮助开发者在处理动态数据结构时优化内存使用,减少不必要的重新分配操作。

核心功能

  • 动态容量预测与调整
  • 内存使用优化
  • 零成本抽象
  • 与标准库容器无缝集成

安装方法

在Cargo.toml中添加依赖:

[dependencies]
capacity_builder = "0.3.0"

基本使用方法

1. 基础容量构建

use capacity_builder::CapacityBuilder;

fn main() {
    let mut builder = CapacityBuilder::new()
        .with_initial_capacity(10)
        .with_growth_factor(2.0);
    
    let mut vec = Vec::with_capacity(builder.current_capacity());
    
    // 模拟添加元素
    for i in 0..20 {
        if vec.len() == vec.capacity() {
            let new_capacity = builder.grow();
            vec.reserve(new_capacity - vec.capacity());
        }
        vec.push(i);
    }
    
    println!("最终容量: {}", vec.capacity());
}

2. 智能容量预测

use capacity_builder::{CapacityBuilder, GrowthStrategy};

fn main() {
    let builder = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Exponential)
        .predict_capacity(1000); // 预测处理1000个元素所需的容量
    
    let mut data: Vec<i32> = Vec::with_capacity(builder);
    
    // 批量添加数据
    for i in 0..1000 {
        data.push(i);
    }
    
    println!("使用容量: {}", data.capacity());
    println!("内存使用优化: {}%", 
        (data.capacity() as f32 / 1000.0 * 100.0) as u32);
}

3. 自定义增长策略

use capacity_builder::{CapacityBuilder, GrowthStrategy};

fn main() {
    // 线性增长策略
    let linear_builder = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Linear(50));
    
    // 指数增长策略(默认)
    let exp_builder = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Exponential);
    
    // 自定义增长函数
    let custom_builder = CapacityBuilder::new()
        .with_custom_growth(|current| current + current / 2);
}

4. 与标准库集合集成

use capacity_builder::CapacityBuilder;
use std::collections::{VecDeque, HashMap};

fn main() {
    // 为VecDeque优化容量
    let capacity = CapacityBuilder::new()
        .with_initial_capacity(100)
        .predict_capacity(500);
    
    let mut deque: VecDeque<i32> = VecDeque::with_capacity(capacity);
    
    // 为HashMap优化容量
    let map_capacity = CapacityBuilder::new()
        .predict_capacity(1000);
    
    let mut map: HashMap<String, i32> = HashMap::with_capacity(map_capacity);
}

高级特性

内存使用监控

use capacity_builder::CapacityBuilder;

fn main() {
    let mut builder = CapacityBuilder::new()
        .enable_memory_tracking();
    
    let mut values = Vec::new();
    
    for i in 0..1000 {
        if values.len() == values.capacity() {
            let new_cap = builder.grow();
            values.reserve(new_cap);
        }
        values.push(i);
    }
    
    println!("内存统计: {:?}", builder.memory_stats());
}

完整示例demo

use capacity_builder::{CapacityBuilder, GrowthStrategy};
use std::collections::{VecDeque, HashMap};

fn main() {
    println!("=== capacity_builder 完整使用示例 ===");
    
    // 示例1: 基础容量构建
    println!("\n1. 基础容量构建示例:");
    let mut builder = CapacityBuilder::new()
        .with_initial_capacity(5)
        .with_growth_factor(1.5);
    
    let mut vec = Vec::with_capacity(builder.current_capacity());
    println!("初始容量: {}", vec.capacity());
    
    for i in 0..15 {
        if vec.len() == vec.capacity() {
            let new_capacity = builder.grow();
            vec.reserve(new_capacity - vec.capacity());
            println!("扩容至: {}", vec.capacity());
        }
        vec.push(i);
    }
    println!("最终容量: {}", vec.capacity());
    
    // 示例2: 智能容量预测
    println!("\n2. 智能容量预测示例:");
    let predicted_builder = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Exponential)
        .predict_capacity(500);
    
    let mut data: Vec<i32> = Vec::with_capacity(predicted_builder);
    for i in 0..500 {
        data.push(i);
    }
    println!("预测容量: {}", data.capacity());
    println!("内存使用率: {:.1}%", (data.capacity() as f32 / 500.0 * 100.0));
    
    // 示例3: 不同增长策略比较
    println!("\n3. 增长策略比较示例:");
    
    let linear = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Linear(20));
    
    let exponential = CapacityBuilder::new()
        .with_growth_strategy(GrowthStrategy::Exponential);
    
    println!("线性增长策略: {:?}", linear);
    println!("指数增长策略: {:?}", exponential);
    
    // 示例4: 标准库集合集成
    println!("\n4. 标准库集合集成示例:");
    
    // VecDeque容量优化
    let deque_capacity = CapacityBuilder::new()
        .with_initial_capacity(50)
        .predict_capacity(200);
    
    let mut deque: VecDeque<String> = VecDeque::with_capacity(deque_capacity);
    for i in 0..150 {
        deque.push_back(format!("item_{}", i));
    }
    println!("VecDeque容量: {}", deque.capacity());
    
    // HashMap容量优化
    let map_capacity = CapacityBuilder::new()
        .predict_capacity(300);
    
    let mut map: HashMap<u32, String> = HashMap::with_capacity(map_capacity);
    for i in 0..250 {
        map.insert(i, format!("value_{}", i));
    }
    println!("HashMap容量: {}", map.capacity());
    
    // 示例5: 内存监控
    println!("\n5. 内存监控示例:");
    let mut monitored_builder = CapacityBuilder::new()
        .enable_memory_tracking()
        .with_initial_capacity(10);
    
    let mut monitored_vec = Vec::new();
    for i in 0..100 {
        if monitored_vec.len() == monitored_vec.capacity() {
            let new_cap = monitored_builder.grow();
            monitored_vec.reserve(new_cap);
        }
        monitored_vec.push(i);
    }
    
    println!("内存统计: {:?}", monitored_builder.memory_stats());
    
    println!("\n=== 示例执行完成 ===");
}

最佳实践

  1. 预分配容量:在处理已知数量级的数据时,使用predict_capacity进行预分配
  2. 选择合适的增长策略:根据使用场景选择线性或指数增长
  3. 监控内存使用:在生产环境中启用内存跟踪功能
  4. 批量操作优化:在批量添加数据前一次性分配足够容量

性能建议

  • 对于频繁扩容的场景,使用指数增长策略
  • 对于内存敏感的应用,使用线性增长策略并设置合理的增长步长
  • 在处理大规模数据时,优先使用predict_capacity进行容量预测

这个库特别适合处理不确定大小的数据流、网络数据包处理、以及需要高效内存管理的应用场景。

回到顶部