Open kyledrake opened 11 years ago
Kyle and I have been discussing SFW's complex interaction with Event Machine for some time. I would appreciate other ruby eventing experts giving Puma a try in wiki farm configurations where "recursive" calls still ocurre.
This is the troublesome request:
https://github.com/WardCunningham/Smallest-Federated-Wiki/blob/master/server/sinatra/server.rb#L319
Notice that there are heuristics that try to short-circuit this call when it is clear that the requested content is from the save server. However, these heuristics don't cover every case.
@kyledrake I remain interested in this improvement but have other issues sneaking in front of this one.
Are multi-threaded servers overkill? Jruby / Rubinius dependencies add complexity.
This improvement is good for both MRI and the threaded versions. MRI will be able to do concurrent IO work with this change. This does not affect JRuby/Rubinius compatibility, and I think that should be treated as a separate issue.
Switching to Puma removes the EventMachine dependency (Puma is pure-ruby with a cross-platform C or Java based HTTP parser) which actually reduces the complexity by taking a lot of code out. EventMachine occasionally has compatibility issues too, it didn't work with Ruby 2.0 for a while IIRC.
Sinatra prior to 1.3 uses "EventMachine" mode of Thin, which disables Ruby threading. This can dramatically decrease throughput on JRuby and Rubinius, because it cannot take advantage of multiple CPU cores with this configuration.
In addition, the MRI (Matz Ruby Implementation) C version of Ruby has a pattern where it will not block on IO if threading is used, because IO will run in the background concurrently while work is being done on other threads.
Unfortunately, Thin with Sinatra < 1.3 forcibly turns threading off due to EventMachine, which makes it so the server has to stop and wait for external IO requests to finish until it can continue serving content (the exception being if you use the special EventMachine drivers, which are very difficult to implement).
Puma does not have these restrictions. It is a fast, clean implementation based on threads, and should run well on all Ruby implementations. It should increase throughput dramatically vs Thin for sites doing a lot of remote IO. It also has a lot of power features like HTTP Keepalive. And best of all, it removes the EventMachine dependency!
More information is available from their web site: http://puma.io
This is a fairly big change, so it would be great if a few people tested it and gave it a thumbs up before merging. An alternative solution to this would be to upgrade to a Sinatra >= 1.3 and the latest version of Thin, which will automatically use threaded mode by default, but this seemed like the more conservative option of the two. That said, ultimately it might be nice to upgrade to 1.3+ as well.
I deployed to Heroku with this change and it appears to be working just fine!