ruby的并发和并行

并发: 厨师同时接收到了2个客人点了的菜单需要处理.
顺序执行: 如果只有一个厨师,那么他只能一个菜单接着一个菜单的去完成.
并行执行: 如果有两个厨师,那么就可以并行,两个人一起做菜.

  1. Ruby MRI为了线程安全,用了GIL只支持单核。任何时刻只有一个线程在运行:当一个Thread阻塞时(比如IO, sleep等),就会切换到另个一线程。 所以就算用了celluloid, puma自动创建多线程的,MRI下每个进程还是单核。
  2. 而Rubinius,JRuby则没有GIL,支持多核(每个线程分配一个cpu)。
  3. 如果MRI下要用多核,就要用sidekiq之类的跑多个worker进程。
  4. 单核不一定比多核慢,很多时候瓶颈不在CPU,而MRI多线程可以保证IO并发,所以性能可能是一样的。
  5. 多进程消耗内存,而且进程间难以通信(只能通过IO之类的)。多线程,直接共享变量(内存)。

https://ruby-china.org/topics/11248

一旦调用外部IO操作,当前线程就会释放CPU内核控制权,另外一个线程就会获得CPU资源。

https://ruby-china.org/topics/23183

https://draveness.me/sidekiq

fiber并发和多线程并发的原理其实差不多,都是当前执行线程(纤程)在执行到外部IO调用的时候,放弃CPU控制权,让另一个线程(纤程)来获取CPU。主要差异在于fiber并发只占用1个操作系统线程,由应用程序来调度纤程;而多线程并发占用n个操作系统线程,由Ruby VM来调度线程。

因此两者的性能差异主要是调度方式带来的:纤程的场景切换非常轻量级,而多线程的场景切换代价高于纤程,因此理论上来说fiber并发性能会更好

https://segmentfault.com/a/1190000010211352

  • 阻塞IO的处理模式的方法很简单:来一个新的连接,我们就新开一个线程来处理这个连接,之后的操作全部由那个线程来完成。
  • 非阻塞IO的核心在于使用一个 Selector 来管理多个通道,之后可以只用一个线程来轮询这个 Selector,看看上面是否有通道是准备好的,当通道准备好可读或可写,然后才去开始真正的读写,这样速度就很快了。我们就完全没有必要给每个通道都起一个线程。

http://www.importnew.com/28021.html

http://20bits.com/article/an-eventmachine-tutorial

https://www.slideshare.net/KyleDrake/hybrid-concurrency-patterns

Celluloid::Proxy::Async 对象会截获方法的调用, 然后保存到 Actor 并发对象的调用队列中, 程序不必等待响应就可以往下执行(异步). 每个并发对象都有一个自己调用队列, 并且按顺序地一个接一个执行里边的方法调用.

https://tonyarcieri.com/a-gentle-introduction-to-nio4r

猜你喜欢

转载自my.oschina.net/u/855913/blog/1627543