开源项目 新年新项目,聊一聊最近在做的 LightIO,IO 性能的免费午餐

jjym · January 01, 2018 · Last by jakit replied at January 03, 2018 · 7277 hits

LightIO 是什么

gevent 是 python 中我最喜欢库之一。

只要 import gevent, 调用下 monkey patch 便会把线程替换为绿色线程,并且把标准库 socket 打上补丁。

每次 IO 操作都会由类库自动切换到其他绿色线程。对用户几乎完全透明,堪称 IO 性能的免费午餐。(建议看这里了解详细: gevent 和异步

身为 rubyist 一直很羡慕隔壁的 gevent。之前虽也有过 em-synchronize 之类使用 Fiber 来表达同步的库( 也可以看这篇了解,不再累述),但总归昙花一现,而且无法做到对用户透明用起来没 gevent 这么方便。

最近耐心看了 gevent 源码,尝试在 ruby 中实现类似能力。产出是 LightIO,目标是为 ruby 用户提供免费的 IO 午餐

当前状态

核心实现起来很简单。但 ruby 的标准库接口庞大,要实现可以 Monkey Patch 的类得花费一番功夫。所以目前只支持有限的几个类 (Socket, TCPSocket, IO 等等)

和 gevent 一样,可以显式的使用 LightIO 来编写代码,目前已经能稳定的支持

如下示例,使用 LightIO 下 的 BeamTCPServer 相比标准库可以获得更好的性能。(基础用法

# echo server example, use telnet to test
LightIO::TCPServer.open('127.0.0.1', 3000) do |server|
  puts "start echo server"
  while (socket = server.accept)
    LightIO::Beam.new(socket){|s| 
      _, port, host = s.peeraddr
      puts "accept connection from #{host}:#{port}"
      loop {s << s.readpartial(4096) rescue break puts("client leave #{host}:#{port}")}
    }
  end
end

另一种精髓用法是使用 LightIO namespace 下的类进行全局 Monkey Patch, 目前仍未完美支持。

Monkey Patch 和 Performance

最近成功的用 LightIO Monkey Patch 了 Webrick,用 ab 本机测了下,性能的确有所提升。 https://github.com/jjyr/lightio_benchmark

在 aws 的 1G 机器上大概每秒多处理 100 个 请求。提升不太明显,原因 1 是和 Webrick 代码本身有关,2 是目前大多数服务器也是异步 IO,只测 Hello World 不会有太大区别。 在更贴近真实环境的情况下 LightIO 的绿色线程会有更大优势。

同时试了下 sinatra 还无法支持..应该是 sinatra 使用了目前 LightIO 没有包含的标准库。

目前的下个目标就定位可以 Monkey Patch sinatra 应用

道阻且长,完美的 Monkey Patch 标准库是难以短时间实现的。

但 LightiO 已经可以提供很好的支持使用,如果有人写一些高性能的 Server/爬虫 等服务,可以考虑使用 LightIO 来实现。

居然沒有人,我先支持一下,希望能坚持做下去👍

2018 年第一赞 👍

我感觉锁的存在让人没办法从 Ruby 级别处理计算密集性能级 IO,只能丢给 C,然后 Ruby 只是在 ready 的时候通知绑定的回调。

Reply to jakit

3.0 提供 Guild 可以无锁 (估计得过几年了),设计很巧妙,可以搜一搜 ko1 的演讲。 设计库的时候我也考虑了 Guild 的情况,看目前的示例 one native-Thread per Guild 这种模型比较科学

需要的话通过 C 或 Rust 这些提高计算能力也算通用做法了,可以接受

Reply to jjym

既然你提到了,我就去看看。

反正之前我打算用 C + pthread 绕过 GIL,结果失败了,很多 var GC 没有 mark,还有一堆 segment fault。

后来 @luikore 前辈赐教后,我自己调整了一番,但是还是很多 bug,像 C 作为 IO 主动通知 Ruby 被动接收最好的选择是 mRuby,没那么多折腾。

总之被 Ruby 的锁折腾得精分,期待 3.0。

You need to Sign in before reply, if you don't have an account, please Sign up first.