Rust内存优化工具get-size-derive2的使用:自动化类型大小计算与内存分析库

Rust内存优化工具get-size-derive2的使用:自动化类型大小计算与内存分析库

示例代码

为结构体派生GetSize

use get_size2::GetSize;

#[derive(GetSize)]
pub struct OwnStruct {
    value1: String,  // 字符串类型,占用堆内存
    value2: u64,     // 基本类型,不占用堆内存
}

fn main() {
    let test = OwnStruct {
        value1: "Hello".into(),  // 5字节的字符串
        value2: 123,
    };

    assert_eq!(test.get_heap_size(), 5);  // 只有value1占用堆内存
}

为枚举派生GetSize

use get_size2::GetSize;

#[derive(GetSize)]
pub enum TestEnum {
    Variant1(u8, u16, u32),  // 基本类型不占用堆内存
    Variant2(String),        // 字符串占用堆内存
    Variant3,                // 单元变体不占用内存
    Variant4{x: String, y: String},  // 命名字段变体
}

#[derive(GetSize)]
pub enum TestEnumNumber {
    Zero = 0,
    One = 1,
    Two = 2,
}

fn main() {
    let test = TestEnum::Variant1(1, 2, 3);
    assert_eq!(test.get_heap_size(), 0);  // 基本类型不占用堆内存

    let test = TestEnum::Variant2("Hello".into());
    assert_eq!(test.get_heap_size(), 5);  // 字符串"Hello"占用5字节

    let test = TestEnum::Variant3;
    assert_eq!(test.get_heap_size(), 0);  // 单元变体不占用内存

    let test = TestEnum::Variant4{x: "Hello".into(), y: "world".into()};
    assert_eq!(test.get_heap_size(), 5 + 5);  // 两个字符串共占用10字节

    let test = TestEnumNumber::One;
    assert_eq!(test.get_heap_size(), 0);  // 纯枚举不占用堆内存
}

完整示例

use get_size2::GetSize;
use std::sync::Arc;

// 基本结构体示例
#[derive(GetSize)]
struct Person {
    name: String,    // 姓名,占用堆内存
    age: u32,        // 年龄,不占用堆内存
    address: String, // 地址,占用堆内存
}

// 枚举示例
#[derive(GetSize)]
enum Message {
    Text(String),     // 文本消息,包含字符串
    Binary(Vec<u8>),  // 二进制消息,包含字节向量
    Empty,            // 空消息
}

// 带有泛型的结构体
#[derive(GetSize)]
struct Container<T> {
    id: u64,  // 不占用堆内存
    data: T,   // 泛型数据,需要T实现GetSize
}

// 忽略特定字段
#[derive(GetSize)]
struct SharedData {
    id: u64,
    #[get_size(ignore)]  // 忽略共享字段的大小计算
    shared: Arc<Vec<u8>>,
}

struct ExternalBuffer;  // 假设的外部缓冲区类型

// 固定大小字段
#[derive(GetSize)]
struct FixedBuffer {
    #[get_size(size = 1024)]  // 指定固定大小为1024字节
    buffer: ExternalBuffer,
}

struct CustomVecType;  // 自定义向量类型
impl CustomVecType {
    fn with_capacity(cap: usize) -> Self { Self }
    fn capacity(&self) -> usize { 0 }
}

// 使用辅助函数计算大小
#[derive(GetSize)]
struct CustomVec {
    #[get_size(size_fn = vec_size_helper)]  // 使用自定义函数计算大小
    data: CustomVecType,
}

// 辅助函数计算自定义向量大小
fn vec_size_helper(vec: &CustomVecType) -> usize {
    vec.capacity() * std::mem::size_of::<u8>()
}

fn main() {
    // 基本结构体使用
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
        address: "123 Main St".to_string(),
    };
    println!("Person堆大小: {}", person.get_heap_size());

    // 枚举使用
    let msg1 = Message::Text("Hello".to_string());
    let msg2 = Message::Binary(vec![0; 100]);
    let msg3 = Message::Empty;
    println!("消息大小: {}, {}, {}", 
        msg1.get_heap_size(),
        msg2.get_heap_size(),
        msg3.get_heap_size());

    // 泛型结构体使用
    let container = Container {
        id: 1,
        data: "Generic data".to_string(),
    };
    println!("容器大小: {}", container.get_heap_size());

    // 共享数据示例
    let shared_vec = Arc::new(vec![0u8; 512]);
    let shared_data = SharedData {
        id: 1,
        shared: Arc::clone(&shared_vec),
    };
    println!("共享数据大小: {}", shared_data.get_heap_size());

    // 固定缓冲区示例
    let fixed_buf = FixedBuffer {
        buffer: ExternalBuffer,
    };
    println!("固定缓冲区大小: {}", fixed_buf.get_heap_size());

    // 自定义计算示例
    let custom = CustomVec {
        data: CustomVecType::with_capacity(200),
    };
    println!("自定义向量大小: {}", custom.get_heap_size());
}

功能说明

get-size-derive2 是一个派生宏,为结构体和枚举提供 GetSize 特性的自定义实现。它会自动计算类型在堆上分配的内存大小,这对于内存优化和分析非常有用。

主要特点:

  1. 自动计算结构体和枚举的堆内存大小
  2. 支持泛型类型
  3. 提供多种处理外部类型的选项:
    • 忽略特定字段 (#[get_size(ignore))
    • 为字段指定固定大小 (#[get_size(size = N))
    • 使用辅助函数计算大小 (#[get_size(size_fn = helper))
  4. 可以忽略特定泛型类型 (#[get_size(ignore(T)))

注意事项:

  1. 不支持联合体(unions)
  2. 所有包含的值默认需要实现 GetSize 特性
  3. 如果字段类型未实现 GetSize,编译时会报错

这个库特别适用于需要精确控制内存使用或分析内存分配情况的场景。


1 回复

Rust内存优化工具get-size-derive2的使用:自动化类型大小计算与内存分析库

get-size-derive2是一个Rust库,用于自动化计算类型的内存占用大小,帮助开发者进行内存分析和优化。

主要功能

  • 自动计算Rust类型的内存占用大小
  • 支持递归计算包含堆分配数据的类型大小
  • 提供派生宏简化使用
  • 帮助识别内存使用热点

安装方法

在Cargo.toml中添加依赖:

[dependencies]
get-size = "0.1"
get-size-derive2 = "0.1"

基本使用方法

1. 为结构体派生GetSize trait

use get_size::GetSize;
use get_size_derive::*;

#[derive(GetSize)]
struct ExampleStruct {
    number: u32,
    text: String,
    numbers: Vec<u64>,
}

2. 获取类型实例的大小

fn main() {
    let example = ExampleStruct {
        number: 42,
        text: "Hello, world!".to_string(),
        numbers: vec![1, 2, 3, 4, 5],
    };
    
    println!("Total size: {} bytes", example.get_size());
    println!("Stack size: {} bytes", std::mem::size_of_val(&example));
    println!("Heap size: {} bytes", example.get_heap_size());
}

高级用法

忽略某些字段

#[derive(GetSize)]
struct IgnoreExample {
    important_data: Vec<u8>,
    #[get_size(ignore)]
    cached_data: Vec<u8>, // 不计入大小计算
}

自定义大小计算

#[derive(GetSize)]
struct CustomSizeExample {
    #[get_size(with = "custom_size_calculation")]
    custom_data: SomeExternalType,
}

fn custom_size_calculation(value: &SomeExternalType) -> usize {
    // 自定义计算逻辑
    value.internal_buffer.len() * std::mem::size_of::<u32>()
}

枚举类型支持

#[derive(GetSize)]
enum ExampleEnum {
    Variant1(u32),
    Variant2(String),
    Variant3 { data: Vec<u8>, flag: bool },
}

实际应用示例

use get_size::GetSize;
use get_size_derive::*;

#[derive(GetSize)]
struct UserProfile {
    id: u64,
    username: String,
    friends: Vec<u64>,
    preferences: Vec<String>,
}

fn analyze_memory_usage() {
    let profile = UserProfile {
        id: 12345,
        username: "rust_lover".to_string(),
        friends: vec![67890, 54321, 98765],
        preferences: vec!["dark_mode".to_string(), "notifications".to_string()],
    };
    
    let total_size = profile.get_size();
    let stack_size = std::mem::size_of_val(&profile);
    let heap_size = profile.get_heap_size();
    
    println!("UserProfile memory analysis:");
    println!("- Total size: {} bytes", total_size);
    println!("- Stack size: {} bytes", stack_size);
    println!("- Heap size: {} bytes ({}%)", 
        heap_size, 
        (heap_size as f64 / total_size as f64 * 100.0) as u32);
    
    // 分析各个字段的内存占用
    println!("\nField breakdown:");
    println!("- id: {} bytes", std::mem::size_of_val(&profile.id));
    println!("- username: {} bytes", profile.username.get_size());
    println!("- friends: {} bytes", profile.friends.get_size());
    println!("- preferences: {} bytes", profile.preferences.get_size());
}

完整示例demo

// 引入必要的trait和派生宏
use get_size::GetSize;
use get_size_derive::*;

// 定义一个包含多种字段类型的复杂结构体
#[derive(GetSize)]
struct MemoryAnalysisDemo {
    id: u64,
    name: String,
    scores: Vec<f32>,
    #[get_size(ignore)]
    debug_info: String,  // 这个字段将被忽略不计
    metadata: Option<Vec<String>>,
}

// 自定义类型
struct CustomBuffer {
    buffer: Vec<u8>,
    scale_factor: f64,
}

// 为自定义类型实现自定义大小计算
#[derive(GetSize)]
struct CustomTypeExample {
    #[get_size(with = "calc_custom_buffer_size")]
    buffer: CustomBuffer,
}

fn calc_custom_buffer_size(buffer: &CustomBuffer) -> usize {
    // 计算buffer大小加上scale_factor的大小
    buffer.buffer.len() + std::mem::size_of_val(&buffer.scale_factor)
}

fn main() {
    // 创建一个复杂结构体实例
    let demo = MemoryAnalysisDemo {
        id: 987654321,
        name: "Memory Analysis Example".to_string(),
        scores: vec![95.5, 87.3, 92.1, 88.7],
        debug_info: "This field is ignored in size calculation".to_string(),
        metadata: Some(vec![
            "created=2023-01-01".to_string(),
            "modified=2023-05-15".to_string()
        ]),
    };

    // 创建一个自定义类型实例
    let custom_example = CustomTypeExample {
        buffer: CustomBuffer {
            buffer: vec![0u8; 1024],  // 1KB buffer
            scale_factor: 1.5,
        },
    };

    // 打印内存分析结果
    println!("=== MemoryAnalysisDemo ===");
    println!("Total size: {} bytes", demo.get_size());
    println!("Stack size: {} bytes", std::mem::size_of_val(&demo));
    println!("Heap size: {} bytes", demo.get_heap_size());
    
    println!("\nField breakdown:");
    println!("- id: {} bytes", std::mem::size_of_val(&demo.id));
    println!("- name: {} bytes", demo.name.get_size());
    println!("- scores: {} bytes", demo.scores.get_size());
    println!("- metadata: {} bytes", demo.metadata.get_size());
    
    println!("\n=== CustomTypeExample ===");
    println!("Total size: {} bytes", custom_example.get_size());
    println!("Custom buffer calculated size: {} bytes", 
        calc_custom_buffer_size(&custom_example.buffer));
}

注意事项

  1. 对于包含指针或引用的类型,计算的是指针本身的大小,而不是指向数据的大小
  2. 递归类型需要特别处理以避免无限循环
  3. 某些特殊类型(如原子类型)可能需要自定义实现
  4. 结果仅供参考,实际内存使用可能因对齐、分配器等因素有所不同

get-size-derive2是内存优化的有力工具,特别适合需要精细控制内存使用的应用场景,如嵌入式开发、高性能计算等。

回到顶部