299 lines
9.5 KiB
Rust
299 lines
9.5 KiB
Rust
//! NUMA感知内存分配示例
|
|
//!
|
|
//! 展示如何使用NUMA感知的内存分配器来优化多socket系统的内存访问性能。
|
|
|
|
use std::alloc::Layout;
|
|
use vm_mem::{
|
|
init_global_numa_allocator, NumaAllocPolicy, NumaAllocator, NumaNodeInfo,
|
|
GlobalNumaAllocator,
|
|
};
|
|
|
|
/// 全局NUMA分配器实例
|
|
#[global_allocator]
|
|
static GLOBAL_NUMA: GlobalNumaAllocator = GlobalNumaAllocator::new();
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("NUMA感知内存分配示例");
|
|
|
|
// 初始化全局NUMA分配器
|
|
init_global_numa_allocator(NumaAllocPolicy::Local)?;
|
|
|
|
// 打印NUMA统计信息
|
|
if let Some(stats) = vm_mem::global_numa_stats() {
|
|
println!("NUMA分配器统计:");
|
|
println!(" 本地分配: {}",
|
|
stats.local_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 远程分配: {}",
|
|
stats.remote_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 失败分配: {}",
|
|
stats.failed_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
}
|
|
|
|
// 示例1: 使用本地分配策略
|
|
demo_local_allocation()?;
|
|
|
|
// 示例2: 使用交错分配策略
|
|
demo_interleaved_allocation()?;
|
|
|
|
// 示例3: 使用绑定分配策略
|
|
demo_bound_allocation()?;
|
|
|
|
// 示例4: 多线程NUMA分配
|
|
demo_multithreaded_allocation()?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 演示本地分配策略
|
|
fn demo_local_allocation() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("\n=== 本地分配策略示例 ===");
|
|
|
|
// 创建测试NUMA节点
|
|
let nodes = vec![
|
|
NumaNodeInfo {
|
|
node_id: 0,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF, // CPU 0-7
|
|
},
|
|
NumaNodeInfo {
|
|
node_id: 1,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF00, // CPU 8-15
|
|
},
|
|
];
|
|
|
|
// 创建本地分配器
|
|
let allocator = NumaAllocator::new(nodes, NumaAllocPolicy::Local);
|
|
|
|
// 分配不同大小的内存块
|
|
let sizes = [1024, 4096, 16384, 65536]; // 1KB, 4KB, 16KB, 64KB
|
|
|
|
for &size in &sizes {
|
|
let layout = Layout::from_size_align(size, 8)?;
|
|
match allocator.allocate(layout) {
|
|
Ok(ptr) => {
|
|
println!("成功分配 {} 字节内存,地址: {:p}", size, ptr.as_ptr());
|
|
// 使用内存...
|
|
unsafe {
|
|
std::ptr::write_bytes(ptr.as_ptr(), 0xAA, size);
|
|
}
|
|
// 释放内存
|
|
allocator.deallocate(ptr, size);
|
|
}
|
|
Err(e) => {
|
|
println!("分配失败: {}", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 打印统计信息
|
|
let stats = allocator.stats();
|
|
println!("本地分配统计:");
|
|
println!(" 本地分配: {}",
|
|
stats.local_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 远程分配: {}",
|
|
stats.remote_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 演示交错分配策略
|
|
fn demo_interleaved_allocation() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("\n=== 交错分配策略示例 ===");
|
|
|
|
// 创建测试NUMA节点
|
|
let nodes = vec![
|
|
NumaNodeInfo {
|
|
node_id: 0,
|
|
total_memory: 4 * 1024 * 1024 * 1024, // 4GB
|
|
available_memory: 3 * 1024 * 1024 * 1024, // 3GB
|
|
cpu_mask: 0xFF, // CPU 0-7
|
|
},
|
|
NumaNodeInfo {
|
|
node_id: 1,
|
|
total_memory: 4 * 1024 * 1024 * 1024, // 4GB
|
|
available_memory: 3 * 1024 * 1024 * 1024, // 3GB
|
|
cpu_mask: 0xFF00, // CPU 8-15
|
|
},
|
|
NumaNodeInfo {
|
|
node_id: 2,
|
|
total_memory: 4 * 1024 * 1024 * 1024, // 4GB
|
|
available_memory: 3 * 1024 * 1024 * 1024, // 3GB
|
|
cpu_mask: 0xFF0000, // CPU 16-23
|
|
},
|
|
];
|
|
|
|
// 创建交错分配器
|
|
let allocator = NumaAllocator::new(nodes, NumaAllocPolicy::Interleave);
|
|
|
|
// 分配多个内存块
|
|
let block_count = 10;
|
|
let block_size = 64 * 1024; // 64KB
|
|
|
|
for i in 0..block_count {
|
|
let layout = Layout::from_size_align(block_size, 8)?;
|
|
match allocator.allocate(layout) {
|
|
Ok(ptr) => {
|
|
println!("交错分配块 {}: {} 字节,地址: {:p}", i, block_size, ptr.as_ptr());
|
|
// 使用内存...
|
|
unsafe {
|
|
std::ptr::write_bytes(ptr.as_ptr(), (i % 256) as u8, block_size);
|
|
}
|
|
// 释放内存
|
|
allocator.deallocate(ptr, block_size);
|
|
}
|
|
Err(e) => {
|
|
println!("分配失败: {}", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 打印统计信息
|
|
let stats = allocator.stats();
|
|
println!("交错分配统计:");
|
|
println!(" 本地分配: {}",
|
|
stats.local_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 远程分配: {}",
|
|
stats.remote_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 演示绑定分配策略
|
|
fn demo_bound_allocation() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("\n=== 绑定分配策略示例 ===");
|
|
|
|
// 创建测试NUMA节点
|
|
let nodes = vec![
|
|
NumaNodeInfo {
|
|
node_id: 0,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF, // CPU 0-7
|
|
},
|
|
NumaNodeInfo {
|
|
node_id: 1,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF00, // CPU 8-15
|
|
},
|
|
];
|
|
|
|
// 创建绑定到节点1的分配器
|
|
let allocator = NumaAllocator::new(nodes, NumaAllocPolicy::Bind(1));
|
|
|
|
// 分配大内存块
|
|
let block_size = 1024 * 1024; // 1MB
|
|
|
|
let layout = Layout::from_size_align(block_size, 8)?;
|
|
match allocator.allocate(layout) {
|
|
Ok(ptr) => {
|
|
println!("绑定分配: {} 字节,地址: {:p},绑定到节点 1",
|
|
block_size, ptr.as_ptr());
|
|
|
|
// 使用内存...
|
|
unsafe {
|
|
std::ptr::write_bytes(ptr.as_ptr(), 0xBB, block_size);
|
|
}
|
|
|
|
// 释放内存
|
|
allocator.deallocate(ptr, block_size);
|
|
}
|
|
Err(e) => {
|
|
println!("绑定分配失败: {}", e);
|
|
}
|
|
}
|
|
|
|
// 打印统计信息
|
|
let stats = allocator.stats();
|
|
println!("绑定分配统计:");
|
|
println!(" 本地分配: {}",
|
|
stats.local_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 远程分配: {}",
|
|
stats.remote_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 演示多线程NUMA分配
|
|
fn demo_multithreaded_allocation() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("\n=== 多线程NUMA分配示例 ===");
|
|
|
|
use std::sync::Arc;
|
|
use std::thread;
|
|
|
|
// 创建测试NUMA节点
|
|
let nodes = vec![
|
|
NumaNodeInfo {
|
|
node_id: 0,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF, // CPU 0-7
|
|
},
|
|
NumaNodeInfo {
|
|
node_id: 1,
|
|
total_memory: 8 * 1024 * 1024 * 1024, // 8GB
|
|
available_memory: 7 * 1024 * 1024 * 1024, // 7GB
|
|
cpu_mask: 0xFF00, // CPU 8-15
|
|
},
|
|
];
|
|
|
|
// 创建共享分配器
|
|
let allocator = Arc::new(NumaAllocator::new(nodes, NumaAllocPolicy::Local));
|
|
|
|
let thread_count = 4;
|
|
let allocations_per_thread = 100;
|
|
let block_size = 4096; // 4KB
|
|
|
|
let mut handles = Vec::new();
|
|
|
|
// 创建多个线程进行内存分配
|
|
for thread_id in 0..thread_count {
|
|
let allocator_clone = allocator.clone();
|
|
let handle = thread::spawn(move || {
|
|
println!("线程 {} 开始分配内存", thread_id);
|
|
|
|
for i in 0..allocations_per_thread {
|
|
let layout = Layout::from_size_align(block_size, 8).unwrap();
|
|
match allocator_clone.allocate(layout) {
|
|
Ok(ptr) => {
|
|
// 使用内存...
|
|
unsafe {
|
|
std::ptr::write_bytes(ptr.as_ptr(),
|
|
((thread_id * 10 + i) % 256) as u8, block_size);
|
|
}
|
|
|
|
// 释放内存
|
|
allocator_clone.deallocate(ptr, block_size);
|
|
}
|
|
Err(_) => {
|
|
eprintln!("线程 {} 分配 {} 失败", thread_id, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
println!("线程 {} 完成内存分配", thread_id);
|
|
});
|
|
|
|
handles.push(handle);
|
|
}
|
|
|
|
// 等待所有线程完成
|
|
for handle in handles {
|
|
handle.join().unwrap();
|
|
}
|
|
|
|
// 打印最终统计信息
|
|
let stats = allocator.stats();
|
|
println!("多线程分配统计:");
|
|
println!(" 本地分配: {}",
|
|
stats.local_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 远程分配: {}",
|
|
stats.remote_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
println!(" 失败分配: {}",
|
|
stats.failed_allocs.load(std::sync::atomic::Ordering::Relaxed));
|
|
|
|
Ok(())
|
|
} |