Skip to content

StreamIntelligenceLab/struct-mem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

struct-mem

A lightweight Rust library for analyzing memory usage of structs, providing stack size and approximate heap memory reporting through derive macros.

Features

  • Stack Size Analysis - Measure the stack footprint of your structs
  • Deep Heap Tracking - Approximate heap memory usage including nested allocations
  • Memory Tree Visualization - Detailed breakdown of memory usage by field
  • Zero Runtime Overhead - All calculations use derive macros
  • Generic Support - Works with generic types and complex nested structures

Installation

Since this crate is not yet published to crates.io, you can use it directly from GitHub:

Option 1: Git Dependency

Add this to your Cargo.toml:

[dependencies]
struct_mem = { git = "https://github.com/StreamIntelligenceLab/struct-mem" }

Option 2: Local Path Dependency

Clone the repository and reference it locally:

git clone https://github.com/StreamIntelligenceLab/struct-mem.git

Then in your Cargo.toml:

[dependencies]
struct_mem = { path = "../struct-mem/struct_mem" }

Usage

Basic Example

use struct_mem::{DeepMem, MemTree, StructMem, report_deep, report_stack, report_tree};

#[derive(StructMem, DeepMem, MemTree)]
struct Person {
    name: String,
    age: u32,
    hobbies: Vec<String>,
}

fn main() {
    let person = Person {
        name:  "Alice".to_string(),
        age: 30,
        hobbies: vec!["reading".to_string(), "coding".to_string()],
    };

    // Method 1: Using trait methods directly
    println!("Stack size:  {}", person.stack_size());
    println!("Heap bytes: {}", person.heap_bytes());
    println!("Total bytes: {}", person.total_bytes());

    // Method 2: Using convenience macros
    report_stack!(&person);
    report_deep!(&person);

    // Method 3: Detailed memory tree
    report_tree! (&person);
}

The Three Traits

1. StructMem - Stack Size Only

Measures only the stack footprint of your struct:

#[derive(StructMem)]
struct Config {
    enabled: bool,
    timeout: u32,
}

let config = Config { enabled: true, timeout: 5000 };
println!("Stack size: {} bytes", config.stack_size());

2. DeepMem - Stack + Heap

Includes both stack and heap allocations:

#[derive(StructMem, DeepMem)]
struct Data {
    buffer: Vec<u8>,
    label: String,
}

let data = Data {
    buffer: vec![0; 1024],
    label: "test".to_string(),
};

println!("Stack:  {} bytes", data.stack_size());
println!("Heap: {} bytes", data.heap_bytes());
println!("Total: {} bytes", data.total_bytes());

3. MemTree - Detailed Breakdown

Provides field-by-field memory analysis:

#[derive(StructMem, DeepMem, MemTree)]
struct Team {
    name: String,
    members: Vec<Person>,
}

let team = Team {
    name: "Engineering".to_string(),
    members: vec![/* ... */],
};

report_tree!(&team);
// Output shows memory usage for each field

Convenience Macros

  • report_stack!(&value) - Print stack size
  • report_deep!(&value) - Print total memory (stack + heap)
  • report_tree!(&value) - Print detailed memory breakdown
  • track_deep!({ expression }) - Track memory of an expression and print it

Complex Examples

Nested Structures

#[derive(StructMem, DeepMem, MemTree)]
struct Team {
    name: String,
    members: Vec<Person>,
    metadata: std::collections::HashMap<String, String>,
}

let team = Team {
    name: "Engineering". to_string(),
    members: vec![
        Person {
            name: "Bob".to_string(),
            age: 25,
            hobbies: vec! ["gaming".to_string()],
        },
        Person {
            name: "Charlie".to_string(),
            age: 35,
            hobbies: vec!["hiking".to_string(), "photography".to_string()],
        },
    ],
    metadata: [
        ("department". to_string(), "R&D".to_string()),
        ("location".to_string(), "Remote".to_string()),
    ].iter().cloned().collect(),
};

report_tree!(&team);

Generic Types

#[derive(StructMem, DeepMem, MemTree)]
struct Config<T> {
    value: T,
    cached: Option<Vec<String>>,
}

let config:  Config<Vec<u32>> = Config {
    value: vec![1, 2, 3, 4, 5],
    cached: Some(vec!["cache1".to_string(), "cache2".to_string()]),
};

report_tree!(&config);

Tracking Memory While Building

let result = track_deep!({
    let mut v = Vec::new();
    for i in 0.. 1000 {
        v. push(format!("Item {}", i));
    }
    v
});

println!("Built vector with {} items", result.len());

Running the Examples

The repository includes a comprehensive example demonstrating all features:

# Clone the repository
git clone https://github.com/StreamIntelligenceLab/struct-mem.git
cd struct-mem

# Run the basic example
cargo run --example basic_test

The example (struct_mem/examples/basic.rs) demonstrates:

  • Basic usage of all three traits
  • Complex nested structures
  • Generic types
  • Collection comparisons (Vec vs HashSet)
  • Memory tracking during construction

Supported Types

The derive macros work with:

  • Primitive types (u8, i32, f64, etc.)
  • Standard collections (Vec, HashMap, HashSet, BTreeMap, etc.)
  • String and &str
  • Option<T> and Result<T, E>
  • Nested structs (that also implement the traits)
  • Generic types

How It Works

  • StructMem: Uses std::mem::size_of: :<T>() to calculate stack size
  • DeepMem: Recursively calculates heap allocations for collections and owned data
  • MemTree: Generates field-by-field breakdowns for detailed analysis

Memory calculations are approximate for heap allocations as they don't account for allocator overhead or internal collection optimizations.

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages