Skip to main content

v0.28.0 Release Notes

EnerOS v0.28.0 Release Notes

Release Date: 2025-11-16 Codename: Turbo Git Tag: v0.28.0 Support Status: Stable Total Crates: 74 (3 new) Test Cases: 9500+ (450+ new)

Overview

EnerOS v0.28.0 “Turbo” is a performance-optimization-focused release that comprehensively accelerates kernel compute-intensive paths. Power system real-time operation is extremely sensitive to latency: power flow calculation needs to complete in milliseconds to support real-time dispatch, constraint validation needs to complete in microseconds to ensure control loop closure, and timeseries data writes need to support millions of points per second to accommodate full-network measurements. v0.28.0 improves critical path performance by 2-8x through SIMD vectorization, memory pools, zero-copy, and other techniques.

This release introduces five core capabilities: Power Flow SIMD Acceleration, Memory Pool, Zero Copy, and Benchmark Suite. All optimizations are completed without changing APIs; user code benefits from performance improvements without modification.

In terms of design philosophy, v0.28.0 adheres to “measurable” — all performance optimizations are backed by benchmarks, eliminating “feels faster” claims; “zero allocation” — hot paths have zero heap allocation, eliminating GC pressure; “cache-friendly” — data layout optimization to improve CPU cache hit rates.

Key Metrics

MetricBeforeAfterImprovement
Power flow (IEEE 118)32ms9ms3.6x
Power flow (1000 nodes)85ms22ms3.9x
Constraint validation (batch)1.2ms0.15ms8x
Timeseries writes500K/s1.8M/s3.6x
Agent message latency P99180μs95μs1.9x
Memory allocation (hot path)120K/s0Infinite

New Features

1. Power Flow SIMD Acceleration

Introduces the eneros-powerflow-simd Crate, using AVX2/AVX-512 instruction sets to accelerate matrix operations. The core of power flow calculation is Jacobian matrix solving; SIMD parallelizes matrix-vector multiplication.

SIMD Matrix Operations

use eneros_powerflow_simd::{SimdSolver, Matrix};

// Auto-select optimal SIMD backend
let solver = SimdSolver::auto_detect();
// Runtime detection: AVX-512 > AVX2 > SSE4.2 > scalar

let mut jacobian = Matrix::new(n, n);
// Build Jacobian matrix...

// SIMD-accelerated LU decomposition
let lu = solver.lu_decompose(&jacobian)?;
let x = solver.solve(&lu, &b)?;

Performance Comparison

Matrix SizeScalarSSE4.2AVX2AVX-512
118x11832ms18ms11ms9ms
500x50065ms36ms22ms17ms
1000x100085ms48ms28ms22ms
5000x5000520ms290ms170ms130ms

Auto Vectorization

// Compiler auto-vectorizes optimized loops
#[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
}
// Use wide crate for explicit 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. Memory Pool

Introduces the eneros-mempool Crate, providing object pools and memory pools to eliminate hot path heap allocation.

Object Pool

use eneros_mempool::{ObjectPool, PoolConfig};

// Create Jacobian matrix object pool
let pool = ObjectPool::<Matrix>::new(PoolConfig {
    initial_size: 16,
    max_size: 64,
    factory: || Matrix::new(118, 118),
});

// Acquire from pool (no allocation)
let mut matrix = pool.acquire().await;
// Use...
matrix.reset();
// Release (no deallocation)
pool.release(matrix);

Memory Pool

use eneros_mempool::{MemoryPool, BlockSize};

// Pre-allocated memory pool
let pool = MemoryPool::new()
    .block_size(BlockSize::KB(4))
    .initial_blocks(1024)
    .max_blocks(8192);

// Allocate from pool (O(1), no system call)
let buf: PinnedBuf = pool.alloc().await?;
// Use buf...
pool.dealloc(buf);  // Return

Allocation Performance Comparison

Allocation MethodSingle Op LatencyThroughputDescription
System malloc85ns120K/sSystem call
jemalloc45ns220K/sThread cache
Object pool8ns120M/sLock-free
Memory pool12ns80M/sPre-allocated

3. Zero Copy

Introduces the eneros-zerocopy Crate, eliminating copies on data transmission paths.

Zero-copy Message Passing

use eneros_zerocopy::{ZeroCopyBuf, SharedMem};

// Traditional: 3 copies
let data = vec![0u8; 4096];  // Heap allocation
agent.send(data).await;       // Serialization copy + network copy

// Zero-copy: 0 copies
let buf = ZeroCopyBuf::allocate(4096);  // Shared memory
// Write data to buf...
agent.send_zerocopy(buf).await?;  // Only pass pointer

IoUring Integration

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

// Linux io_uring: true zero-copy I/O
let ring = IoUring::new(256)?;

// Direct from disk to network, bypassing user space
ring.submit(OpCode::SendFile {
    fd: file_fd,
    socket: socket_fd,
    offset: 0,
    len: 4096,
}).await?;

Zero-copy Coverage Paths

PathTraditionalZero-copyDescription
Inter-agent messages3 copies0 copiesShared memory
Timeseries writes2 copies0 copiesDirect I/O
Topology broadcastN copies1 copyCOW
Log writes2 copies0 copiesio_uring

4. Data Layout Optimization

Cache-friendly optimization for hot path data structures to improve CPU cache hit rates.

SoA Layout

// Traditional AoS (Array of Structures)
struct BusLegacy {
    id: u32,
    voltage: f64,
    angle: f64,
    load_p: f64,
    load_q: f64,
}
// Accessing voltage loads the entire struct, wasting cache

// Optimized SoA (Structure of Arrays)
struct BusArray {
    ids: Vec<u32>,
    voltages: Vec<f64>,   // Contiguous storage
    angles: Vec<f64>,
    load_ps: Vec<f64>,
    load_qs: Vec<f64>,
}
// Accessing voltage[i] prefetches adjacent voltages, high cache hit rate

Performance Comparison

Data StructureTraverse 1000 NodesCache Hit Rate
AoS (legacy)2.5ms42%
SoA (optimized)0.8ms91%

5. Benchmark Suite

Introduces the eneros-bench Crate, providing a complete benchmark suite covering all critical paths.

Benchmark

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);
}

Continuous Benchmarking

// Benchmark results auto-recorded, supports regression detection
let baseline = BenchmarkSuite::load_baseline("v0.27.0")?;
let current = suite.run().await?;

let regression = current.compare(&baseline);
for r in regression.regressions() {
    println!("Performance regression: {} slowed by {:.1}%", r.name, r.regression_pct);
}

Benchmark Coverage

ModuleBenchmark CountKey MetricRegression Threshold
Power flow12Latency5%
Constraint validation8Throughput5%
Timeseries engine10Write/Query5%
Topology engine6Traverse/Query5%
Agent runtime8Message latency10%

Improvements

  • Compilation Optimization: Enabled LTO with codegen-units=1, binary size reduced by 15%, performance improved by 3%
  • Memory Allocator: Default to jemalloc, multi-threaded allocation performance improved by 40%
  • Async Runtime: Upgraded tokio to 1.40, scheduler performance improved by 8%
  • Warmup Mechanism: Critical paths warmed up at startup, eliminating first-call cold start

Bug Fixes

  • Fixed eneros-powerflow-simd falling back to scalar when AVX-512 unavailable (#2805)
  • Fixed eneros-mempool object pool lock contention under high concurrency (#2810)
  • Fixed eneros-zerocopy shared memory not properly released on process exit (#2815)
  • Fixed eneros-bench excessive result fluctuation in CI environments (#2820)

Breaking Changes

  • Matrix internal layout: Changed from AoS to SoA; external API unchanged but repr(C) no longer guaranteed
  • Agent::send: Added send_zerocopy method; original send remains compatible

Upgrade Guide

  1. Run cargo update -p eneros-powerflow-simd
  2. Recompile to get SIMD acceleration (requires AVX2-supported CPU)
  3. If depending on Matrix memory layout, update code
  4. Refer to docs/migration/v0.28.0.md for detailed migration steps