跳到主内容

v0.28.0 版本说明

EnerOS v0.28.0 版本说明

发布日期:2025-11-16 版本代号:Turbo Git Tag:v0.28.0 支持状态:稳定(Stable) Crate 总数:74(新增 3 个) 测试用例数:9500+(新增 450+)

概述

EnerOS v0.28.0「Turbo」是性能优化专项版本,对内核计算密集型路径进行全面加速。电力系统实时运行对延迟极其敏感:潮流计算需要在毫秒级完成以支撑实时调度,约束校验需要在微秒级完成以保证控制闭环,时序数据写入需要支撑百万点/秒以容纳全网量测。v0.28.0 通过 SIMD 向量化、内存池、零拷贝等技术,将关键路径性能提升 2-8 倍。

本版本引入了五大核心能力:潮流计算 SIMD 加速(Power Flow SIMD)、内存池(Memory Pool)、零拷贝(Zero Copy)、基准测试套件(Benchmark Suite)。所有优化均在不改变 API 的前提下完成,用户代码无需修改即可获得性能提升。

设计哲学上,v0.28.0 坚持「可测量」——所有性能优化均有基准测试支撑,杜绝「感觉变快」;「零分配」——热路径零堆分配,消除 GC 压力;「缓存友好」——数据布局优化以提高 CPU 缓存命中率。

关键数据

指标优化前优化后提升倍数
潮流计算(IEEE 118)32ms9ms3.6x
潮流计算(1000 节点)85ms22ms3.9x
约束校验(批量)1.2ms0.15ms8x
时序写入50 万/s180 万/s3.6x
Agent 消息延迟 P99180μs95μs1.9x
内存分配(热路径)12 万/s0无限

新特性

1. 潮流计算 SIMD 加速

引入 eneros-powerflow-simd Crate,利用 AVX2/AVX-512 指令集加速矩阵运算。潮流计算的核心是雅可比矩阵求解,SIMD 可将矩阵-向量乘法并行化。

SIMD 矩阵运算

use eneros_powerflow_simd::{SimdSolver, Matrix};

// 自动选择最优 SIMD 后端
let solver = SimdSolver::auto_detect();
// 运行时检测:AVX-512 > AVX2 > SSE4.2 > 标量

let mut jacobian = Matrix::new(n, n);
// 构建雅可比矩阵...

// SIMD 加速的 LU 分解
let lu = solver.lu_decompose(&jacobian)?;
let x = solver.solve(&lu, &b)?;

性能对比

矩阵规模标量SSE4.2AVX2AVX-512
118x11832ms18ms11ms9ms
500x50065ms36ms22ms17ms
1000x100085ms48ms28ms22ms
5000x5000520ms290ms170ms130ms

自动向量化

// 编译器自动向量化已优化的循环
#[inline]
pub fn dot_product(a: &[f64], b: &[f64]) -> f64 {
    assert!(a.len() == b.len());
    let mut sum = 0.0;
    for i in 0..a.len() {
        sum += a[i] * b[i];
    }
    sum
}
// 使用 wide crate 显式 SIMD
use wide::f64x4;
pub fn dot_product_simd(a: &[f64], b: &[f64]) -> f64 {
    let mut sum = f64x4::splat(0.0);
    for chunk in a.chunks_exact(4).zip(b.chunks_exact(4)) {
        let va = f64x4::from_slice_unaligned(chunk.0);
        let vb = f64x4::from_slice_unaligned(chunk.1);
        sum += va * vb;
    }
    sum.horizontal_sum()
}

2. 内存池

引入 eneros-mempool Crate,提供对象池与内存池,消除热路径堆分配。

对象池

use eneros_mempool::{ObjectPool, PoolConfig};

// 创建雅可比矩阵对象池
let pool = ObjectPool::<Matrix>::new(PoolConfig {
    initial_size: 16,
    max_size: 64,
    factory: || Matrix::new(118, 118),
});

// 从池中借出(无分配)
let mut matrix = pool.acquire().await;
// 使用...
matrix.reset();
// 归还(无释放)
pool.release(matrix);

内存池

use eneros_mempool::{MemoryPool, BlockSize};

// 预分配的内存池
let pool = MemoryPool::new()
    .block_size(BlockSize::KB(4))
    .initial_blocks(1024)
    .max_blocks(8192);

// 从池分配(O(1),无系统调用)
let buf: PinnedBuf = pool.alloc().await?;
// 使用 buf...
pool.dealloc(buf);  // 归还

分配性能对比

分配方式单次耗时吞吐说明
系统 malloc85ns12 万/s系统调用
jemalloc45ns22 万/s线程缓存
对象池8ns1.2 亿/s无锁
内存池12ns8000 万/s预分配

3. 零拷贝

引入 eneros-zerocopy Crate,在数据传输路径上消除拷贝。

零拷贝消息传递

use eneros_zerocopy::{ZeroCopyBuf, SharedMem};

// 传统方式:3 次拷贝
let data = vec![0u8; 4096];  // 堆分配
agent.send(data).await;       // 序列化拷贝 + 网络拷贝

// 零拷贝方式:0 次拷贝
let buf = ZeroCopyBuf::allocate(4096);  // 共享内存
// 写入数据到 buf...
agent.send_zerocopy(buf).await?;  // 仅传递指针

IoUring 集成

use eneros_zerocopy::iouring::{IoUring, OpCode};

// Linux io_uring:真正的零拷贝 I/O
let ring = IoUring::new(256)?;

// 直接从磁盘到网络,不经过用户态
ring.submit(OpCode::SendFile {
    fd: file_fd,
    socket: socket_fd,
    offset: 0,
    len: 4096,
}).await?;

零拷贝覆盖路径

路径传统零拷贝说明
Agent 间消息3 次拷贝0 次共享内存
时序写入2 次拷贝0 次直接 I/O
拓扑广播N 次拷贝1 次COW
日志写入2 次拷贝0 次io_uring

4. 数据布局优化

对热路径数据结构进行缓存友好性优化,提高 CPU 缓存命中率。

SoA 布局

// 传统 AoS(Array of Structures)
struct BusLegacy {
    id: u32,
    voltage: f64,
    angle: f64,
    load_p: f64,
    load_q: f64,
}
// 访问 voltage 时加载整个 struct,浪费缓存

// 优化 SoA(Structure of Arrays)
struct BusArray {
    ids: Vec<u32>,
    voltages: Vec<f64>,   // 连续存储
    angles: Vec<f64>,
    load_ps: Vec<f64>,
    load_qs: Vec<f64>,
}
// 访问 voltage[i] 时预取相邻电压,缓存命中率高

性能对比

数据结构遍历 1000 节点缓存命中率
AoS (legacy)2.5ms42%
SoA (optimized)0.8ms91%

5. 基准测试套件

引入 eneros-bench Crate,提供完整的基准测试套件,覆盖所有关键路径。

基准测试

use eneros_bench::{Benchmark, BenchmarkSuite};

let suite = BenchmarkSuite::new("powerflow")
    .bench(Benchmark::new("ieee-14", || {
        solver.solve(&ieee14_network)
    }))
    .bench(Benchmark::new("ieee-118", || {
        solver.solve(&ieee118_network)
    }))
    .bench(Benchmark::new("ieee-300", || {
        solver.solve(&ieee300_network)
    }));

let results = suite.run().await?;
for r in results {
    println!("{}: {:.2}ms (±{:.2}%)",
        r.name, r.mean_ms, r.variation_pct);
}

持续基准

// 基准结果自动记录,支持回归检测
let baseline = BenchmarkSuite::load_baseline("v0.27.0")?;
let current = suite.run().await?;

let regression = current.compare(&baseline);
for r in regression.regressions() {
    println!("性能回退: {} 慢了 {:.1}%", r.name, r.regression_pct);
}

基准测试覆盖

模块基准数关键指标回归阈值
潮流计算12延迟5%
约束校验8吞吐5%
时序引擎10写入/查询5%
拓扑引擎6遍历/查询5%
Agent 运行时8消息延迟10%

改进

  • 编译优化:启用 LTO 与 codegen-units=1,二进制体积减少 15%,性能提升 3%
  • 内存分配器:默认使用 jemalloc,多线程分配性能提升 40%
  • 异步运行时:升级 tokio 至 1.40,调度器性能提升 8%
  • 预热机制:关键路径在启动时预热,消除首次调用冷启动

Bug 修复

  • 修复 eneros-powerflow-simd 在 AVX-512 不可用时回退至标量的问题(#2805)
  • 修复 eneros-mempool 在高并发下对象池锁竞争的问题(#2810)
  • 修复 eneros-zerocopy 共享内存在进程退出时未正确释放的问题(#2815)
  • 修复 eneros-bench 在 CI 环境下结果波动过大的问题(#2820)

破坏性变更

  • Matrix 内部布局:从 AoS 改为 SoA,外部 API 不变但 repr(C) 不再保证
  • Agent::send:新增 send_zerocopy 方法,原 send 保持兼容

升级指南

  1. 执行 cargo update -p eneros-powerflow-simd
  2. 重新编译以获得 SIMD 加速(需 AVX2 支持的 CPU)
  3. 如依赖 Matrix 的内存布局,需更新代码
  4. 参考 docs/migration/v0.28.0.md 获取详细迁移步骤