jdb_alloc : Aligned Memory Allocator for Direct I/O
Table of Contents
Overview
jdb_alloc provides 4KB-aligned memory allocation for Direct I/O operations. It offers two core types:
AlignedBuf: Owning buffer with automatic memory managementRawIoBuf: Non-owning,Copybuffer for zero-copy async I/O
Designed for high-performance database storage engines and Buffer Pool implementations.
Features
- 4KB alignment for Direct I/O (O_DIRECT)
- Zero-copy buffer slicing
Copysemantics for async I/O compatibility- Arena-style memory management
- Integration with compio async runtime
- OS-optimized zero page allocation (COW)
Installation
Usage
Basic Allocation
use ;
// Allocate zeroed 4KB page
let buf = page.unwrap;
assert_eq!;
// Allocate with custom size
let mut buf = zeroed.unwrap;
buf.as_mut = 42;
Zero-Copy I/O
use AlignedBuf;
let mut buf = zeroed.unwrap;
// Convert to RawIoBuf for async I/O
let raw = unsafe ;
// RawIoBuf is Copy, can be passed to async operations
// while retaining local reference
Buffer Pool Arena Pattern
use ;
// Allocate large arena (e.g., 32KB = 8 pages)
let arena = zeroed.unwrap;
// Slice into frames
let frames: = unsafe ;
assert_eq!;
Extend Buffer
use AlignedBuf;
let mut buf = with_cap.unwrap;
buf.extend.unwrap;
buf.extend.unwrap;
assert_eq!;
API Reference
Constants
| Name | Value | Description |
|---|---|---|
PAGE_SIZE |
4096 | Standard page size |
ALIGNMENT |
4096 | Direct I/O alignment requirement |
AlignedBuf
Owning aligned buffer. Releases memory on drop.
| Method | Description |
|---|---|
with_cap(cap) |
Create with capacity (uninitialized) |
zeroed(size) |
Create zeroed buffer |
page() |
Create 4KB zeroed page |
as_raw() |
Convert to RawIoBuf (unsafe) |
as_raw_view() |
Get RawIoBuf view (unsafe) |
slice_into_raws(chunk) |
Slice into multiple RawIoBuf (unsafe) |
extend(data) |
Append data |
try_clone() |
Clone without panic on OOM |
into_raw_parts() |
Deconstruct (leak memory) |
from_raw_parts(ptr, len, cap) |
Reconstruct (unsafe) |
RawIoBuf
Non-owning buffer wrapper. Implements Copy for async I/O ergonomics.
| Method | Description |
|---|---|
new(ptr, cap) |
Create wrapper (unsafe) |
with_len(len) |
Set length (chainable) |
from_slice(slice) |
Create from mutable slice |
slice(offset, len) |
Slice for reading (unsafe) |
slice_data(offset, len) |
Slice for writing (unsafe) |
slice_unchecked(offset, len) |
Slice without checks (unsafe) |
as_slice() |
Get byte slice |
as_mut_slice() |
Get mutable byte slice |
Compio Integration
Both types implement:
IoBuf- Read buffer traitIoBufMut- Write buffer traitSetBufInit- Initialize buffer length
Design
Architecture
graph TD
A[AlignedBuf] -->|owns| B[Aligned Memory]
A -->|as_raw| C[RawIoBuf]
A -->|slice_into_raws| D[Multiple RawIoBuf]
C -->|Copy| E[Async I/O Operation]
D -->|frames| F[Buffer Pool]
Memory Layout
AlignedBuf (Owning)
┌─────────────────────────────────────┐
│ ptr: NonNull<u8> (4KB aligned) │
│ len: usize (initialized) │
│ cap: usize (allocated) │
└─────────────────────────────────────┘
│
▼
RawIoBuf (Non-owning, Copy)
┌─────────────────────────────────────┐
│ ptr: *mut u8 (borrowed) │
│ len: usize │
│ cap: usize │
└─────────────────────────────────────┘
Call Flow
- Allocate
AlignedBufas arena - Slice into
RawIoBufframes viaslice_into_raws - Pass
RawIoBufto async I/O (Copy semantics) - I/O completion updates buffer content
- Arena (
AlignedBuf) manages lifetime
Tech Stack
| Component | Technology |
|---|---|
| Language | Rust 2024 Edition |
| Async I/O | compio-buf |
| Error Handling | thiserror |
| Memory | std::alloc (aligned) |
Project Structure
jdb_alloc/
├── src/
│ ├── lib.rs # Core types: AlignedBuf, RawIoBuf
│ └── error.rs # Error definitions
├── tests/
│ └── main.rs # Unit tests
├── readme/
│ ├── en.md # English documentation
│ └── zh.md # Chinese documentation
└── Cargo.toml
History
Direct I/O emerged in the 1990s as databases sought to bypass the OS page cache for predictable performance. The O_DIRECT flag, introduced in Linux 2.4.10 (2001), requires strict alignment—typically 512 bytes for older disks, 4KB for modern SSDs.
The 4KB alignment matches the standard page size on most architectures, a design dating back to the VAX-11/780 (1977) which popularized 512-byte disk sectors and 4KB virtual memory pages.
Modern NVMe SSDs with 4KB logical blocks make this alignment even more critical. Misaligned I/O can cause read-modify-write cycles, degrading performance by 2-10x.
This library draws inspiration from database systems like PostgreSQL's buffer manager and RocksDB's aligned buffer implementation, optimized for Rust's ownership model and async I/O patterns.
About
This project is an open-source component of js0.site ⋅ Refactoring the Internet Plan.
We are redefining the development paradigm of the Internet in a componentized way. Welcome to follow us:
jdb_alloc : Direct I/O 对齐内存分配器
目录
概述
jdb_alloc 提供 4KB 对齐的内存分配,用于 Direct I/O 操作。核心类型:
AlignedBuf: 拥有所有权的缓冲区,自动管理内存RawIoBuf: 无所有权、可Copy的缓冲区,用于零拷贝异步 I/O
专为高性能数据库存储引擎和 Buffer Pool 设计。
特性
- 4KB 对齐,支持 Direct I/O (O_DIRECT)
- 零拷贝缓冲区切片
Copy语义,兼容异步 I/O- Arena 风格内存管理
- 集成 compio 异步运行时
- OS 优化的零页分配 (COW)
安装
使用
基础分配
use ;
// 分配零初始化的 4KB 页
let buf = page.unwrap;
assert_eq!;
// 自定义大小分配
let mut buf = zeroed.unwrap;
buf.as_mut = 42;
零拷贝 I/O
use AlignedBuf;
let mut buf = zeroed.unwrap;
// 转换为 RawIoBuf 用于异步 I/O
let raw = unsafe ;
// RawIoBuf 是 Copy 的,可传递给异步操作
// 同时保留本地引用
Buffer Pool Arena 模式
use ;
// 分配大型 arena(如 32KB = 8 页)
let arena = zeroed.unwrap;
// 切分为帧
let frames: = unsafe ;
assert_eq!;
扩展缓冲区
use AlignedBuf;
let mut buf = with_cap.unwrap;
buf.extend.unwrap;
buf.extend.unwrap;
assert_eq!;
API 参考
常量
| 名称 | 值 | 描述 |
|---|---|---|
PAGE_SIZE |
4096 | 标准页大小 |
ALIGNMENT |
4096 | Direct I/O 对齐要求 |
AlignedBuf
拥有所有权的对齐缓冲区。Drop 时释放内存。
| 方法 | 描述 |
|---|---|
with_cap(cap) |
创建指定容量(未初始化) |
zeroed(size) |
创建零初始化缓冲区 |
page() |
创建 4KB 零初始化页 |
as_raw() |
转换为 RawIoBuf (unsafe) |
as_raw_view() |
获取 RawIoBuf 视图 (unsafe) |
slice_into_raws(chunk) |
切分为多个 RawIoBuf (unsafe) |
extend(data) |
追加数据 |
try_clone() |
克隆,OOM 时不 panic |
into_raw_parts() |
解构(泄漏内存) |
from_raw_parts(ptr, len, cap) |
重建 (unsafe) |
RawIoBuf
无所有权的缓冲区包装器。实现 Copy 以便于异步 I/O。
| 方法 | 描述 |
|---|---|
new(ptr, cap) |
创建包装器 (unsafe) |
with_len(len) |
设置长度(链式调用) |
from_slice(slice) |
从可变切片创建 |
slice(offset, len) |
切片用于读取 (unsafe) |
slice_data(offset, len) |
切片用于写入 (unsafe) |
slice_unchecked(offset, len) |
无检查切片 (unsafe) |
as_slice() |
获取字节切片 |
as_mut_slice() |
获取可变字节切片 |
Compio 集成
两种类型都实现:
IoBuf- 读缓冲区 traitIoBufMut- 写缓冲区 traitSetBufInit- 初始化缓冲区长度
设计
架构
A[AlignedBuf] -->|拥有| B[对齐内存]
A -->|as_raw| C[RawIoBuf]
A -->|slice_into_raws| D[多个 RawIoBuf]
C -->|Copy| E[异步 I/O 操作]
D -->|帧| F[Buffer Pool]
内存布局
AlignedBuf (拥有所有权)
┌─────────────────────────────────────┐
│ ptr: NonNull<u8> (4KB 对齐) │
│ len: usize (已初始化) │
│ cap: usize (已分配) │
└─────────────────────────────────────┘
│
▼
RawIoBuf (无所有权, Copy)
┌─────────────────────────────────────┐
│ ptr: *mut u8 (借用) │
│ len: usize │
│ cap: usize │
└─────────────────────────────────────┘
调用流程
- 分配
AlignedBuf作为 arena - 通过
slice_into_raws切分为RawIoBuf帧 - 将
RawIoBuf传递给异步 I/O(Copy 语义) - I/O 完成后更新缓冲区内容
- Arena (
AlignedBuf) 管理生命周期
技术栈
| 组件 | 技术 |
|---|---|
| 语言 | Rust 2024 Edition |
| 异步 I/O | compio-buf |
| 错误处理 | thiserror |
| 内存 | std::alloc (对齐) |
项目结构
jdb_alloc/
├── src/
│ ├── lib.rs # 核心类型: AlignedBuf, RawIoBuf
│ └── error.rs # 错误定义
├── tests/
│ └── main.rs # 单元测试
├── readme/
│ ├── en.md # 英文文档
│ └── zh.md # 中文文档
└── Cargo.toml
历史
Direct I/O 诞生于 1990 年代,数据库系统为获得可预测的性能而绕过 OS 页缓存。Linux 2.4.10 (2001) 引入的 O_DIRECT 标志要求严格对齐——旧磁盘通常 512 字节,现代 SSD 为 4KB。
4KB 对齐与大多数架构的标准页大小一致,这一设计可追溯到 VAX-11/780 (1977),它普及了 512 字节磁盘扇区和 4KB 虚拟内存页。
现代 NVMe SSD 采用 4KB 逻辑块,使对齐更加关键。未对齐的 I/O 会导致读-修改-写循环,性能下降 2-10 倍。
本库借鉴了 PostgreSQL 缓冲区管理器和 RocksDB 对齐缓冲区实现,针对 Rust 所有权模型和异步 I/O 模式优化。
关于
本项目为 js0.site ⋅ 重构互联网计划 的开源组件。
我们正在以组件化的方式重新定义互联网的开发范式,欢迎关注: