lighty 的生活

lighty 开发者博客

Linux 上的异步 IO

trunk/ 刚获得了 Linux 原生 AIO 的支持。

我基于 libaio 实现了异步 IO,libaio 是针对 2.6.x 内核的 aio 系统调用的一个最小封装。

实现

由于 libaio 基本没有文档,所以让它工作起来有点棘手,但是嘿……这就是我们是黑客的原因 :)

异步文件 IO 支持是 Linux 2.6.9 及更高版本的一部分,应该在每个最新的 Linux 系统上都可用。一个名为 libaio 的独立库提供了非常简单的封装,并被用作新网络后端的基础。

思路是

  1. 在 /dev/shm 中创建一个缓冲区并 mmap() 它
  2. 从源文件到 mmap() 缓冲区启动异步 read()
  3. 等待数据就绪
  4. 使用 sendfile() 将数据从 /dev/shm 发送到网络套接字

对性能而言很重要的是:数据从不复制到用户空间。我们只将其从内核的一侧移动到另一侧。

技术探索

遗憾的是,我不得不将 pthread 添加到依赖项中。在一个单线程服务器中拥有线程有点奇怪,但这是必要的。

fdevent_poll() 会等待 fd 事件 1 秒。在它等待期间,服务器也在等待。异步通知的处理也是阻塞的,我们无法让它们在其中一个完成后立即返回。

如果需要,我们会启动一个 io-getevent 线程,与 fdevent_poll() 调用并行运行。首先返回的调用会通过向进程发送 SIGUSR1 来中断另一个调用。它使得等待中的调用(poll() 和 io_getevents())以 EINTR 返回,我们就可以继续处理这两个调用中的一个的结果。

基准测试

作为测试平台,我们有一个通过两块硬盘组成的 RAID1 (linux md)

  • ST3160827AS (SATA, 每块 120Mb)
  • nVidia Corporation CK8S 作为 SATA 控制器
  • AMD Athlon™ 64 处理器 3000+
  • Linux 2.6.16.21-0.25-xen (SuSE 10.1)

siege, 700Mb

我将比较 linux-sendfile 与 linux-aio-sendfile。

$ siege —reps=1 -c 1 —benchmark http://127.0.0.1:1025/file-700M


|并发|非 aio|aio [512k]|aio [1M]|
|1|52.38 MB/秒 [9% 空闲]|89.85 MB/秒 [70% 空闲]|107.50 MB/秒 [67% 空闲] |
|2|39.94 MB/秒 [8% 空闲]|94.52 MB/秒 [70% 空闲]| 92.74 MB/秒 [70% 空闲]
|
|5|35.45 MB/秒 [7% 空闲]|31.81 MB/秒 [86% 空闲]|72.84 MB/秒 [70% 空闲]|
|10|… |25.22 MB/秒 [82% 空闲]| 32.87 MB/秒 [90%] 空闲 |

现在,比吞吐量更重要的是可以用于其他任务的 CPU 时间。

下一步是什么?

接下来是错误修复、负载测试(更多并行连接)、随机负载等……

lighttpd

请注意,我们不接受超过 3 个月发布的帖子的评论! 此外,请使用我们的错误跟踪器报告错误,并使用我们的 IRC 频道 #lighttpd@libera 进行聊天。

« Jan 都在忙些什么? lighty 1.5.0 和 linux-aio »