Closed openhood closed 14 years ago
First, all network access should go through EM. Using the stock Redis client will kill your scalability. You ideally should use a fibered, EM-aware Redis client. I'm not aware of one.
sleep() puts the current thread to sleep. Since there's only one thread in your process, this halts all processing - which is what you are seeing. You need to use the proper EM facilities to do the same thing. Replace "sleep" with "Fiber.sleep" in your code above, with this monkeypatch.
class Fiber
def self.sleep(sec)
f = Fiber.current
EM.add_timer(sec) do
f.resume
end
Fiber.yield
end
end
None of this has to do with rack-fiber_pool, which is why it's not in the readme.
You can find an EM-Redis lib here : http://github.com/madsimian/em-redis with a more recent fork here http://github.com/superfeedr/em-redis.
That's an EM-aware client but it is not Fiber-aware. Here's how I 'fibered' em-jack:
http://github.com/mperham/em-jack/commit/09ed5e3917933809942a23bdfa5ff7bafae6b7c6
Note the code in the spec: it's purely procedural, despite using EM under the covers.
bean = EMJack::Connection.new
bean.fiber!
bean.put("hello!")
job = bean.reserve
job.body.should == "hello!"
job.delete
I suspect redis to be so fast that em-redis would not be any faster, but it's impossible to be sure without benchmarks.
It's not speed, it's context-switching. EM allows your process to work on other things while waiting on network traffic. Keep studying EM and you'll grok it eventually.
Ok thanks a lot for your explanations.
Hello,
I set up this very small example:
This is exactly the place I would need fibers because with threads it works but I can only create 950 threads or so before it crashes, whereas I can create many more fibers without issue. It does really seem to run requests inside fibers, and send the proper async info to thin. However as soon as the sleep command is running, no more request can be done which make the whole fiber-thing pretty useless. Is there a special thing I should be using instead of sleep to make the current fiber sleep while allow other fibers to run? Here is a simplified example showing the same exact issue:
If I call "/instant" I get the response immediately. If however I call "/slower" and in another tab I try to call "/instant", I don't get response from "/instant" until "/slower" has finished. What am I doing wrong? Perhaps could you add an additional example (a bit like the previous one) in the README showing how putting each request in a fiber can be used to achieve concurrency.