Rust内联数组库inline-array的使用,高效内存布局与固定大小数组操作优化

Rust内联数组库inline-array的使用,高效内存布局与固定大小数组操作优化

主要特性

InlineArray是一个高度优化的字节数组实现,具有以下特点:

  • 栈上仅占用8字节空间
  • 7字节及以下的数组直接内联存储在栈上
  • 长数组使用两种优化引用计数结构:
    • 长度≤255的数组:AtomicU8引用计数 + u8长度字段(仅2字节开销)
    • 更大数组:AtomicU16引用计数 + 48位长度字段
  • 引用计数达到最大值时会自动复制数据

内存对齐保证

所有InlineArray实例都保证存储的数组按8字节边界对齐,这对零拷贝序列化非常重要。

示例代码

use inline_array::InlineArray;

// 创建InlineArray
let ia = InlineArray::from(b"yo!");

// 获取可变引用
let mut_ref = ia.make_mut();

// 克隆数组
let cloned = ia.clone();

// 获取数组长度
let len = ia.len();

// 访问数组元素
let first_byte = ia[0];

完整示例demo

use inline_array::InlineArray;

fn main() {
    // 创建短数组(内联存储)
    let short = InlineArray::from(b"short");
    println!("Short array length: {}", short.len()); // 5
    
    // 创建长数组(堆存储)
    let long_data = vec![0u8; 100];
    let long = InlineArray::from(&long_data[..]);
    println!("Long array length: {}", long.len()); // 100
    
    // 克隆数组(共享数据)
    let long_clone = long.clone();
    
    // 修改数组(写时复制)
    let mut mutable = long.make_mut();
    mutable[0] = 42;
    
    // 检查修改后的值
    println!("Modified first byte: {}", mutable[0]); // 42
    println!("Original first byte: {}", long[0]); // 0
    
    // 对齐检查
    println!("Alignment: {}", std::mem::align_of_val(&*mutable)); // 8
}

其他特性与限制

功能特性:

  • 默认禁用的serde序列化支持

限制:

  • 不支持超过48位长度的数组(最大256TB)

1 回复

Rust内联数组库inline-array的使用指南

概述

inline-array是一个Rust库,专注于提供高效内存布局的固定大小数组操作。它通过内联存储优化了小数组的性能,避免了堆分配的开销,同时为固定大小数组提供了便捷的操作接口。

主要特性

  • 零堆分配的内联存储
  • 固定大小数组的高效操作
  • 与标准库Vec类似的API体验
  • 编译时大小检查
  • 针对小数组优化的内存布局

安装

在Cargo.toml中添加依赖:

[dependencies]
inline-array = "0.1"

基本使用

创建内联数组

use inline_array::InlineArray;

// 创建一个可容纳5个元素的内联数组
let mut arr = InlineArray::<i32, 5>::new();

// 从迭代器创建
let arr = InlineArray::from_iter([1, 2, 3].into_iter());

添加和访问元素

let mut arr = InlineArray::<_, 3>::new();
arr.push(1);
arr.push(2);
arr.push(3);

println!("First element: {}", arr[0]);  // 访问元素
println!("Array length: {}", arr.len());

数组操作

// 遍历
for item in &arr {
    println!("{}", item);
}

// 映射转换
let doubled: InlineArray<_, 3> = arr.iter().map(|x| x * 2).collect();

// 拼接数组
let mut arr1 = InlineArray::from_iter([1, 2].into_iter());
let arr2 = InlineArray::from_iter([3, 4].into_iter());
arr1.extend(arr2);

高级用法

编译时大小检查

// 尝试添加超过容量的元素会在运行时panic
let mut arr = InlineArray::<_, 2>::new();
arr.push(1);
arr.push(2);
// arr.push(3);  // 这会panic,因为超过了容量

与标准Vec互转

let arr = InlineArray::from_iter([1, 2, 3].into_iter());
let vec: Vec<_> = arr.into_iter().collect();

let back_to_arr: InlineArray<_, 3> = vec.into_iter().collect();

模式匹配

let arr = InlineArray::from_iter([1, 2, 3].into_iter());
match arr.as_slice() {
    [1, 2, 3] => println!("匹配成功"),
    _ => println!("不匹配"),
}

性能建议

  1. 对于小数组(通常小于32个元素),使用InlineArray可以获得更好的性能
  2. 如果数组大小在编译时已知,优先使用InlineArray而非Vec
  3. 避免频繁创建和销毁,复用数组对象

实际应用示例

矩阵运算

type Vector3 = InlineArray<f64, 3>;

fn dot_product(a: &Vector3, b: &Vector3) -> f64 {
    a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()
}

let v1 = Vector3::from_iter([1.0, 2.0, 3.0].into_iter());
let v2 = Vector3::from_iter([4.0, 5.0, 6.0].into_iter());
println!("点积结果: {}", dot_product(&v1, &v2));

固定大小缓存

struct RecentItems<T, const N: usize> {
    items: InlineArray<T, N>,
}

impl<T, const N: usize> RecentItems<T, N> {
    fn push(&mut self, item: T) {
        if self.items.len() == N {
            self.items.pop();
        }
        self.items.insert(0, item);
    }
}

完整示例demo

use inline_array::InlineArray;

fn main() {
    // 示例1: 基本创建和操作
    let mut arr = InlineArray::<i32, 5>::new();
    arr.push(10);
    arr.push(20);
    arr.push(30);
    println!("数组内容: {:?}", arr.as_slice());
    
    // 示例2: 从迭代器创建
    let from_iter = InlineArray::from_iter([1, 2, 3, 4].into_iter());
    println!("从迭代器创建的数组: {:?}", from_iter.as_slice());
    
    // 示例3: 数组操作
    let doubled: InlineArray<_, 4> = from_iter.iter().map(|x| x * 2).collect();
    println!("翻倍后的数组: {:?}", doubled.as_slice());
    
    // 示例4: 向量点积计算
    type Vector3 = InlineArray<f64, 3>;
    let v1 = Vector3::from_iter([1.0, 2.0, 3.0].into_iter());
    let v2 = Vector3::from_iter([4.0, 5.0, 6.0].into_iter());
    println!("向量点积结果: {}", dot_product(&v1, &v2));
    
    // 示例5: 固定大小缓存使用
    let mut cache = RecentItems::<i32, 3> {
        items: InlineArray::new()
    };
    cache.push(100);
    cache.push(200);
    cache.push(300);
    cache.push(400);  // 这会移除第一个元素100
    println!("缓存内容: {:?}", cache.items.as_slice());
}

fn dot_product(a: &InlineArray<f64, 3>, b: &InlineArray<f64, 3>) -> f64 {
    a.iter().zip(b.iter()).map(|(x, y)| x * y).sum()
}

struct RecentItems<T, const N: usize> {
    items: InlineArray<T, N>,
}

impl<T, const N: usize> RecentItems<T, N> {
    fn push(&mut self, item: T) {
        if self.items.len() == N {
            self.items.pop();
        }
        self.items.insert(0, item);
    }
}

这个完整示例展示了inline-array库的主要功能,包括基本操作、向量计算和缓存实现。你可以直接复制这段代码到你的Rust项目中运行。

回到顶部