Linux 性能实战 | 第 15 篇 磁盘 IO 性能分析与瓶颈定位 [特殊字符]

🔗 从 Swap 到磁盘:存储性能的最后一环

在第十四章中,我们深入探讨了 Swap 机制------当物理内存不足时,内核将不活跃的匿名页 swap 到磁盘。我们诊断了一个自动驾驶系统的性能崩溃问题,发现每秒 2345KB 的 swap in 和 3456KB 的 swap out 导致 CPU iowait 达到 90%,响应延迟从 50ms 飙升到 5000ms。

这个案例揭示了一个关键问题:磁盘 IO 是现代计算机系统中最慢的环节 。虽然 CPU 的速度以纳秒计,内存以微秒计,但磁盘 IO 的延迟却以毫秒计------相差 6 个数量级(100 万倍)!

在自动驾驶系统中,磁盘 IO 性能直接影响着:

  • 传感器数据录制:6 个摄像头 + 2 个激光雷达,每秒产生 ~500MB 数据
  • 数据回放:加载历史 rosbag 文件,需要每秒读取 ~1GB 数据
  • 高精地图查询:从 100GB 的地图数据库中查询路径信息
  • 日志记录:每秒数千条日志写入磁盘

本章关键问题

  • IOPS、吞吐量、延迟三者的关系是什么?
  • 为什么顺序 IO 比随机 IO 快 100 倍?
  • 如何选择正确的 IO 调度器?
  • SSD 性能未达预期,如何诊断?

📊 磁盘 IO 三大性能指标:IOPS、吞吐量、延迟

1. 三大指标的定义

磁盘 IO 性能三角
关系
关系
关系
IOPS

每秒 IO 操作次数

Input/Output Operations Per Second
吞吐量

每秒传输数据量

MB/s 或 GB/s
延迟

单次 IO 操作耗时

ms 或 μs

IOPS (每秒 IO 操作次数)

复制代码
IOPS = 1 秒内完成的读写操作总数
  • 高 IOPS:适合小文件、随机访问(数据库、元数据操作)
  • 低 IOPS:大量小 IO 操作会导致 IOPS 饱和

吞吐量 (Throughput)

复制代码
吞吐量 = 1 秒内传输的数据总量 (MB/s)
  • 高吞吐量:适合大文件、顺序访问(视频、日志、备份)
  • 关系吞吐量 = IOPS × 平均 IO 大小

延迟 (Latency)

复制代码
延迟 = 从发起 IO 请求到完成的时间 (ms 或 μs)
  • 低延迟:实时系统、交互式应用
  • 关系IOPS ≈ 队列深度 / 平均延迟

2. 三者的权衡关系

示例 1:顺序读取大文件(视频回放)

复制代码
IO 大小:1MB
IOPS:100 次/秒(低)
吞吐量:100 IOPS × 1MB = 100 MB/s(高)
延迟:10ms(中等)

示例 2:随机读取小文件(数据库查询)

复制代码
IO 大小:4KB
IOPS:10,000 次/秒(高)
吞吐量:10,000 IOPS × 4KB = 40 MB/s(低)
延迟:0.1ms(低)

不可能三角

  • 高 IOPS + 高吞吐量 + 低延迟 → 需要顶级硬件(NVMe SSD)
  • 低成本硬件 → 必须在三者间取舍

🔀 顺序 IO vs 随机 IO:100 倍的性能鸿沟

1. 机械硬盘(HDD)的工作原理

顺序 IO
寻道时间

~5ms (一次)
连续读取

1ms/MB
100MB 总耗时: ~105ms

吞吐量: 950 MB/s
随机 IO
寻道时间

~5ms
旋转延迟

~4ms
数据传输

~1ms
总延迟: ~10ms

IOPS: 100
HDD 结构
磁盘盘片

7200 RPM 旋转
磁头

机械臂移动
磁道

HDD 的三个阶段

  1. 寻道时间(Seek Time):磁头移动到目标磁道(~5ms)
  2. 旋转延迟(Rotational Latency):等待数据扇区旋转到磁头下(~4ms,7200RPM)
  3. 数据传输(Transfer Time):读取数据(~150MB/s)

性能对比

IO 模式 IO 大小 IOPS 吞吐量 延迟
随机读取 4KB ~100 0.4 MB/s 10ms
顺序读取 1MB ~100 100 MB/s 10ms

差异 :顺序读取的吞吐量是随机读取的 250 倍

2. SSD 的随机 IO 优势

SSD 工作原理

  • 无机械部件,全电子访问
  • 寻道时间 = 0
  • 旋转延迟 = 0
  • 只有闪存读取延迟(~0.1ms)

性能对比(SATA SSD):

IO 模式 IO 大小 IOPS 吞吐量 延迟
随机读取 4KB ~10,000 40 MB/s 0.1ms
顺序读取 1MB ~500 500 MB/s 2ms

差异 :顺序读取的吞吐量只是随机读取的 12.5 倍(HDD 是 250 倍)

3. 自动驾驶场景分析

场景 1:传感器数据录制(顺序写入)

bash 复制代码
# 6 个摄像头 + 2 个激光雷达,每秒 500MB
# 需要的性能:
IOPS: 50-100(大 IO 块)
吞吐量: 500 MB/s
推荐硬件: SATA SSD 或 NVMe SSD

场景 2:点云数据库查询(随机读取)

bash 复制代码
# 从 100GB 数据库中查询特定区域的点云
# 需要的性能:
IOPS: 5,000-10,000(小查询)
吞吐量: 20-40 MB/s
推荐硬件: NVMe SSD(HDD 会非常慢)

性能测试

bash 复制代码
# 测试随机读 IOPS
fio --name=random-read --ioengine=libaio --iodepth=32 --rw=randread \
    --bs=4k --direct=1 --size=4G --numjobs=4 --runtime=60 --group_reporting

# 测试顺序读吞吐量
fio --name=seq-read --ioengine=libaio --iodepth=32 --rw=read \
    --bs=1M --direct=1 --size=4G --numjobs=1 --runtime=60 --group_reporting

典型结果(NVMe SSD):

复制代码
随机读 (4KB):  IOPS=120,000, BW=468MB/s, lat=0.27ms
顺序读 (1MB):  IOPS=3,200,  BW=3,200MB/s, lat=10ms

📏 队列深度:并发的力量

1. 队列深度的定义

队列深度(Queue Depth):同时发送给磁盘的 IO 请求数量。
磁盘 IO 队列 应用程序 磁盘 IO 队列 应用程序 队列深度 = 4 IO 请求 1 IO 请求 2 IO 请求 3 IO 请求 4 并发处理 4 个请求 完成 1 完成 2 返回结果 1 返回结果 2 IO 请求 5 IO 请求 6

队列深度 = 1(串行):

复制代码
请求 1 → 完成 → 请求 2 → 完成 → 请求 3 → ...
延迟:1ms × 100 次 = 100ms
IOPS:100 次 / 0.1s = 1,000

队列深度 = 32(并行):

复制代码
请求 1-32 → 同时处理 → 完成
延迟:1ms(单次)
IOPS:32 / 0.001s = 32,000

2. 队列深度对性能的影响

测试脚本

bash 复制代码
# 测试不同队列深度的性能
for qd in 1 4 8 16 32 64 128; do
    echo "Testing QD=$qd"
    fio --name=test --ioengine=libaio --iodepth=$qd --rw=randread \
        --bs=4k --direct=1 --size=1G --runtime=10 --numjobs=1
done

结果(NVMe SSD):

队列深度 IOPS 延迟 吞吐量
1 8,500 0.12ms 33 MB/s
4 32,000 0.12ms 125 MB/s
8 58,000 0.14ms 227 MB/s
16 95,000 0.17ms 371 MB/s
32 120,000 0.27ms 469 MB/s
64 125,000 0.51ms 488 MB/s
128 126,000 1.02ms 492 MB/s

观察

  • QD=1 → QD=32:IOPS 提升 14 倍
  • QD=32 → QD=128:IOPS 提升很小(已饱和)
  • 最佳队列深度:32-64(平衡性能与延迟)

3. 应用程序如何控制队列深度

直接 IO(绕过 Page Cache)

c 复制代码
#include <fcntl.h>
#include <libaio.h>

// 打开文件(O_DIRECT 绕过缓存)
int fd = open("/dev/nvme0n1", O_RDONLY | O_DIRECT);

// 初始化 AIO 上下文(队列深度 32)
io_context_t ctx = 0;
io_setup(32, &ctx);

// 准备 32 个 IO 请求
struct iocb *iocbs[32];
for (int i = 0; i < 32; i++) {
    iocbs[i] = malloc(sizeof(struct iocb));
    io_prep_pread(iocbs[i], fd, buffer[i], 4096, i * 4096);
}

// 提交 32 个请求(队列深度 = 32)
io_submit(ctx, 32, iocbs);

// 等待完成
struct io_event events[32];
io_getevents(ctx, 32, 32, events, NULL);

缓冲 IO(使用 Page Cache)

bash 复制代码
# 系统会自动调整队列深度
# 查看当前队列深度
cat /sys/block/nvme0n1/queue/nr_requests
# 输出:128(默认)

# 增加队列深度(提升并发)
echo 256 > /sys/block/nvme0n1/queue/nr_requests

⚙️ IO 调度器:内核的"交通警察"

1. IO 调度器的作用

IO 调度器负责决定内核如何将 IO 请求发送给硬件

  • 合并请求:相邻的 IO 请求合并为一个(减少开销)
  • 排序请求:按照磁盘位置排序(减少 HDD 寻道时间)
  • 公平性:防止某个进程"饿死"其他进程

块设备层
IO 调度器
应用层
进程 A

读请求
进程 B

写请求
进程 C

读请求
调度算法

合并、排序、调度
设备队列
磁盘

2. 传统 IO 调度器(单队列)

noop (No Operation)

  • 策略:先进先出(FIFO),不排序不合并
  • 适用:SSD、NVMe、虚拟机(底层已优化)
  • 优点:CPU 开销最小
  • 缺点:无优化

deadline

  • 策略:按截止时间调度,防止请求饿死
  • 适用:数据库、实时系统
  • 优点:延迟可预测
  • 缺点:吞吐量可能较低

cfq (Completely Fair Queuing)

  • 策略:按进程公平分配带宽
  • 适用:桌面系统、多用户环境
  • 优点:公平性好
  • 缺点:复杂,CPU 开销大

3. 多队列 IO 调度器(Linux 5.0+)

现代 NVMe SSD 有多个硬件队列(可达 64 个),传统单队列调度器无法充分利用。

none

  • 无调度器(直接发送给硬件)
  • 适用:高性能 NVMe

mq-deadline

  • deadline 的多队列版本
  • 适用:通用场景

bfq (Budget Fair Queuing)

  • 按 IO 带宽预算分配
  • 适用:桌面、低延迟场景

kyber

  • 动态调整队列深度
  • 适用:云环境、混合负载

4. 查看和设置 IO 调度器

查看当前调度器

bash 复制代码
cat /sys/block/nvme0n1/queue/scheduler
# 输出:[none] mq-deadline kyber bfq
# [] 表示当前使用的调度器

临时设置

bash 复制代码
echo mq-deadline > /sys/block/nvme0n1/queue/scheduler

永久设置(通过 udev 规则):

bash 复制代码
# 创建 udev 规则
cat << 'EOF' | sudo tee /etc/udev/rules.d/60-scheduler.rules
# NVMe SSD 使用 none
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"

# SATA SSD 使用 mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"

# HDD 使用 bfq
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
EOF

# 重新加载 udev 规则
sudo udevadm control --reload-rules
sudo udevadm trigger

5. 调度器选择建议

硬件类型 负载类型 推荐调度器 理由
NVMe SSD 通用 none 硬件已优化,调度器反而增加延迟
SATA SSD 通用 mq-deadline 平衡性能与延迟
HDD 通用 bfq 减少寻道时间,提升公平性
数据库 低延迟 mq-deadline 可预测的延迟
桌面系统 交互式 bfq 响应性好
自动驾驶数据采集 高吞吐量 none (NVMe) 最大化写入带宽

🛠️ 实战案例:传感器数据录制性能优化

1. 问题现象

一个自动驾驶数据采集系统,配备了 6 个摄像头和 2 个激光雷达,理论数据流量约 500MB/s。但在实际录制时,系统频繁丢帧,磁盘写入速度只有 150MB/s,远低于 NVMe SSD 的标称性能(3000MB/s)。

初步检查

bash 复制代码
iostat -x 1

输出

复制代码
Device  r/s   w/s   rMB/s   wMB/s  rrqm/s  wrqm/s  %util  avgqu-sz  await  r_await  w_await
nvme0n1 0.0  3254   0.00    150.2    0.0     0.0    85.2      2.3    0.71    0.00     0.71

异常点

  • wMB/s = 150MB/s:远低于预期的 500MB/s
  • w/s = 3254:每秒 3254 次写操作
  • avgqu-sz = 2.3:平均队列深度只有 2.3(太低!)
  • %util = 85.2%:设备利用率很高,但吞吐量低

计算平均 IO 大小

复制代码
平均 IO 大小 = 150MB/s / 3254 次/s ≈ 47KB

问题定位:IO 大小太小(47KB),队列深度不足(2.3),无法发挥 NVMe 的性能。

2. 深入诊断:blktrace

使用 blktrace 追踪 IO 请求:

bash 复制代码
# 启动 blktrace(记录 10 秒)
sudo blktrace -d /dev/nvme0n1 -o trace &
sleep 10
sudo killall blktrace

# 分析 IO 模式
blkparse -i trace | head -100

输出示例

复制代码
259,0    0        1     0.000000000 12345  Q  WS 204800 + 96 [data_recorder]
259,0    0        2     0.000023456 12345  G  WS 204800 + 96 [data_recorder]
259,0    0        3     0.000045678 12345  I  WS 204800 + 96 [data_recorder]
259,0    0        4     0.000067890 12345  D  WS 204800 + 96 [data_recorder]
259,0    0        5     0.000789012 12345  C  WS 204800 + 96 [0]

分析

  • WS:写入,同步(sync)
  • 204800 + 96:起始扇区 + 扇区数(96 扇区 × 512B = 48KB)
  • 时间戳差异:从 Q(队列)到 C(完成)约 0.79ms

发现:应用程序使用 48KB 的同步写入,且队列深度很小。

3. 优化方案

方案 1:增大 IO 块大小

cpp 复制代码
// 原始代码(小 IO)
void RecordSensorData(const SensorFrame& frame) {
    // 每帧单独写入(48KB)
    write(fd, &frame, sizeof(frame));
    fsync(fd);  // ❌ 每次都同步
}

// 优化后(批量写入)
class SensorRecorder {
private:
    std::vector<SensorFrame> buffer;
    static constexpr size_t BUFFER_SIZE = 100;  // 缓冲 100 帧

public:
    void RecordSensorData(const SensorFrame& frame) {
        buffer.push_back(frame);
        
        // 缓冲区满时批量写入
        if (buffer.size() >= BUFFER_SIZE) {
            Flush();
        }
    }
    
    void Flush() {
        // 一次写入 4.8MB(100 帧 × 48KB)
        write(fd, buffer.data(), buffer.size() * sizeof(SensorFrame));
        fsync(fd);  // 100 帧同步一次
        buffer.clear();
    }
};

方案 2:使用异步 IO(io_uring)

cpp 复制代码
#include <liburing.h>

struct io_uring ring;

void InitRecorder() {
    // 初始化 io_uring(队列深度 64)
    io_uring_queue_init(64, &ring, 0);
}

void RecordSensorData(const SensorFrame& frame) {
    // 获取 SQE(Submission Queue Entry)
    struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
    
    // 准备写入请求
    io_uring_prep_write(sqe, fd, &frame, sizeof(frame), offset);
    
    // 提交请求(非阻塞)
    io_uring_submit(&ring);
    
    // 无需等待完成(异步)
}

void WaitCompletion() {
    struct io_uring_cqe *cqe;
    io_uring_wait_cqe(&ring, &cqe);
    io_uring_cqe_seen(&ring, cqe);
}

方案 3:调整内核参数

bash 复制代码
# 增加队列深度
echo 512 > /sys/block/nvme0n1/queue/nr_requests

# 禁用调度器(NVMe 直接发送)
echo none > /sys/block/nvme0n1/queue/scheduler

# 增加 writeback 缓存
sysctl -w vm.dirty_ratio=40
sysctl -w vm.dirty_background_ratio=10

4. 优化效果

再次运行 iostat

bash 复制代码
iostat -x 1

优化后

复制代码
Device  r/s   w/s   rMB/s   wMB/s  rrqm/s  wrqm/s  %util  avgqu-sz  await  r_await  w_await
nvme0n1 0.0   104   0.00    520.3    0.0     0.0    45.2     32.5    0.31    0.00     0.31

改善

指标 优化前 优化后 改善
写入带宽 150 MB/s 520 MB/s ↑ 247%
写入次数 3254 次/s 104 次/s ↓ 97%
平均 IO 大小 47KB 5MB ↑ 106 倍
队列深度 2.3 32.5 ↑ 14 倍
设备利用率 85% 45% ↓ 47%(更高效)
延迟 0.71ms 0.31ms ↓ 56%

丢帧率:从 15% 降至 0%


🔧 IO 性能监控工具

1. iostat - 实时 IO 统计

基础用法

bash 复制代码
# 每秒刷新一次
iostat -x 1

# 显示更详细的信息
iostat -xz 1
# -x: 扩展统计
# -z: 跳过无活动的设备

关键字段解释

复制代码
r/s, w/s:     每秒读/写次数(IOPS)
rMB/s, wMB/s: 每秒读/写数据量(吞吐量)
rrqm/s:       每秒合并的读请求数
avgqu-sz:     平均队列长度(重要!)
await:        平均等待时间(ms)
%util:        设备利用率(接近 100% 说明饱和)

性能瓶颈判断

复制代码
%util = 100% + avgqu-sz > 10  → 设备饱和
await > 10ms (SSD)            → 延迟过高
r/s + w/s 接近设备 IOPS 上限   → IOPS 饱和

2. iotop - 进程级 IO 监控

bash 复制代码
# 显示哪些进程在进行 IO
sudo iotop

# 只显示有 IO 的进程
sudo iotop -o

# 按累计 IO 排序
sudo iotop -a

输出

复制代码
Total DISK READ: 45.67 M/s | Total DISK WRITE: 234.56 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
12345  be/4  root       0.00 B/s  234.56 M/s  0.00 %  85.23 % data_recorder
23456  be/4  user      45.67 M/s    0.00 B/s  0.00 %  12.34 % rosbag_player

3. blktrace - IO 请求追踪

bash 复制代码
# 记录 IO 事件
sudo blktrace -d /dev/nvme0n1 -o trace &
# 运行负载
sleep 10
sudo killall blktrace

# 分析 IO 模式
blkparse -i trace > trace.txt

# 查看 IO 延迟分布
btt -i trace.blktrace.*

IO 请求的生命周期

复制代码
Q (Queued)     → 请求进入内核队列
G (Get request)→ 分配请求结构体
I (Inserted)   → 插入 IO 调度器
D (Dispatched) → 发送给驱动
C (Completed)  → 完成

Q2C 延迟 = 总延迟(应用程序视角)
D2C 延迟 = 设备延迟(硬件性能)

4. fio - IO 性能基准测试

测试随机读 IOPS

bash 复制代码
fio --name=randread --ioengine=libaio --iodepth=32 \
    --rw=randread --bs=4k --direct=1 --size=4G \
    --numjobs=4 --runtime=60 --group_reporting \
    --filename=/dev/nvme0n1

测试顺序写吞吐量

bash 复制代码
fio --name=seqwrite --ioengine=libaio --iodepth=32 \
    --rw=write --bs=1M --direct=1 --size=10G \
    --numjobs=1 --runtime=60 --group_reporting \
    --filename=/dev/nvme0n1

自动驾驶场景测试

bash 复制代码
# 模拟传感器数据录制(顺序写,大块)
fio --name=sensor-record \
    --ioengine=libaio --iodepth=64 \
    --rw=write --bs=256k --direct=1 \
    --size=50G --numjobs=1 --runtime=60

# 模拟点云数据库查询(随机读,小块)
fio --name=pointcloud-query \
    --ioengine=libaio --iodepth=32 \
    --rw=randread --bs=16k --direct=1 \
    --size=20G --numjobs=4 --runtime=60

💽 NVMe vs SATA SSD vs HDD:性能天壤之别

1. 三种存储介质对比

指标 HDD (7200 RPM) SATA SSD NVMe SSD
接口带宽 6 Gbps (SATA) 6 Gbps (SATA) 32 Gbps (PCIe 4.0 x4)
随机读 IOPS ~100 ~10,000 ~500,000
顺序读吞吐 ~150 MB/s ~550 MB/s ~7,000 MB/s
随机读延迟 ~10 ms ~0.1 ms ~0.02 ms
队列深度 1-4 32 64-256
价格 ($/TB) ~$20 ~$80 ~$120

性能差异可视化
顺序读吞吐
HDD

150 MB/s
SATA SSD

550 MB/s

3.7x
NVMe SSD

7,000 MB/s

46x
随机读 IOPS
HDD

100 IOPS
SATA SSD

10,000 IOPS

100x
NVMe SSD

500,000 IOPS

5,000x

2. 自动驾驶系统存储方案

方案 1:全 NVMe(高性能)

复制代码
主存储: 2TB NVMe SSD(PCIe 4.0)
- 传感器数据录制
- 点云数据库
- 操作系统和应用程序

成本: ~$240
优点: 最佳性能,低延迟
缺点: 容量有限,成本高

方案 2:NVMe + SATA SSD(平衡)

复制代码
热数据: 500GB NVMe SSD
- 当前录制的数据
- 频繁查询的地图数据

冷数据: 4TB SATA SSD
- 历史录制数据
- 归档日志

成本: ~$60 + $320 = $380
优点: 性能与容量兼顾
缺点: 需要数据分层管理

方案 3:NVMe + HDD(经济)

复制代码
热数据: 500GB NVMe SSD
- 实时处理数据

归档: 8TB HDD
- 长期存储

成本: ~$60 + $160 = $220
优点: 最经济,大容量
缺点: 访问归档数据很慢

3. 验证硬件性能

检查 NVMe 链路速度

bash 复制代码
# 查看 PCIe 信息
sudo lspci -vv | grep -A 20 "Non-Volatile"

输出

复制代码
LnkCap: Port #0, Speed 16GT/s, Width x4  ⬅️ PCIe 4.0 x4 (最大 ~8GB/s)
LnkSta: Speed 16GT/s, Width x4           ⬅️ 实际运行在最高速度

如果发现

复制代码
LnkSta: Speed 8GT/s, Width x4   ⬅️ 只跑 PCIe 3.0(限速)

原因

  • 主板插槽只支持 PCIe 3.0
  • NVMe 插在了共享带宽的插槽上
  • 解决:更换到 CPU 直连的 M.2 插槽

📝 总结与最佳实践

核心要点

  • IOPS、吞吐量、延迟的权衡:无法同时最大化,需根据负载选择
  • 顺序 IO 比随机 IO 快 100 倍(HDD)或 12 倍(SSD)
  • 队列深度是关键:QD=1 vs QD=32,IOPS 可提升 10-15 倍
  • IO 调度器选择:NVMe 用 none,SATA SSD 用 mq-deadline,HDD 用 bfq
  • 大 IO 块 + 高队列深度 = 高性能

IO 性能诊断清单

✅ 快速检查

bash 复制代码
# 查看 IO 统计
iostat -x 1

# 查看进程 IO
sudo iotop -o

# 查看队列深度和调度器
cat /sys/block/nvme0n1/queue/nr_requests
cat /sys/block/nvme0n1/queue/scheduler

✅ 深度分析

bash 复制代码
# 追踪 IO 请求
sudo blktrace -d /dev/nvme0n1 -o trace
blkparse -i trace

# 性能基准测试
fio --name=test --ioengine=libaio --iodepth=32 \
    --rw=randread --bs=4k --runtime=60

✅ 性能优化

bash 复制代码
# 调整队列深度
echo 512 > /sys/block/nvme0n1/queue/nr_requests

# 设置调度器
echo none > /sys/block/nvme0n1/queue/scheduler

# 调整 writeback 参数
sysctl -w vm.dirty_ratio=40

自动驾驶 IO 优化建议

场景 负载特征 优化方案
传感器录制 顺序写,大块,高吞吐 NVMe + 大 IO 块(1-4MB) + 异步 IO + QD=64
数据回放 顺序读,大块 madvise(MADV_SEQUENTIAL) + readahead
点云查询 随机读,小块,高 IOPS NVMe + 直接 IO + QD=32
日志记录 小块写,低延迟 批量缓冲 + 异步 fsync

关键代码模式

cpp 复制代码
// ✅ 高性能 IO 模式
1. 使用大 IO 块(1-4MB)
2. 异步 IO(io_uring 或 libaio)
3. 直接 IO(O_DIRECT)绕过 Page Cache
4. 高队列深度(32-64)
5. 批量处理(减少系统调用)

// ❌ 低性能 IO 模式
1. 小 IO 块(4KB)
2. 同步 IO(阻塞等待)
3. 缓冲 IO + 频繁 fsync
4. 队列深度 = 1
5. 每次操作都系统调用

🎯 下一章预告

在本章中,我们深入探讨了磁盘 IO 性能的三大指标------IOPS、吞吐量、延迟,理解了顺序 IO 与随机 IO 的巨大性能差异(100 倍),掌握了队列深度对性能的关键影响(10-15 倍提升),学会了选择合适的 IO 调度器,并通过一个传感器数据录制系统的优化案例,将写入带宽从 150MB/s 提升到 520MB/s。

在下一章《文件系统性能优化与分析》中,我们将深入文件系统层面的性能优化:

  • Ext4、XFS、Btrfs 的性能特点与适用场景
  • 元数据操作对性能的影响(文件创建、删除、stat)
  • fsync、fdatasync、sync 的区别与性能开销
  • 日志模式(ordered、writeback、journal)的选择
  • Direct IO、Buffered IO、mmap 的性能对比
  • 文件碎片对性能的影响与优化
  • inotify、fanotify 的性能开销

通过真实的自动驾驶日志系统和数据回放场景,我们将揭示文件系统对整体性能的深远影响。敬请期待!🚀

相关推荐
YJlio5 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
l1t5 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
小白同学_C5 小时前
Lab4-Lab: traps && MIT6.1810操作系统工程【持续更新】 _
linux·c/c++·操作系统os
今天只学一颗糖5 小时前
1、《深入理解计算机系统》--计算机系统介绍
linux·笔记·学习·系统架构
山塘小鱼儿7 小时前
本地Ollama+Agent+LangGraph+LangSmith运行
python·langchain·ollama·langgraph·langsimth
码说AI7 小时前
python快速绘制走势图对比曲线
开发语言·python
不做无法实现的梦~7 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
wait_luky7 小时前
python作业3
开发语言·python
SQL必知必会8 小时前
SQL 窗口帧:ROWS vs RANGE 深度解析
数据库·sql·性能优化