There is definitely annoying memory overhead with multiprocess (vs. multithreaded) architectures, but it's on the order of 2x-8x, not 100x. And that's 2x-8x the code size of the application, not data size - you only need duplicate interpreter objects, anything at the app or framework level (like templates or data files) can be stored in read-only shared memory or just COW'd with no writes. (It's technically not even every interpreter object - a number of function objects are completely static data that will never have additional references made, and so COW means they'll be shared perpetually between processes.)
Unicorn is a pre-forking multiprocess server so I don't know why it would be using an event loop.
Why threads over processes? Because memory isn't cheap when you don't own it yourself.
Shrug why not? You get a different (easier?) programming model where you can use blocking IO rather than an event loop.
> on the order of 2x-8x, not 100x
Yeah, but that 2x might be the difference between one virtual machine flavor and the next price up.
This is a fair point, but the issue might be about memory usage, not speed. A unicorn setup might have two to eight worker processes to service HTTP requests. Even with copy-on-write-friendly garbage collection, the memory usage of each additional process is significant. On the other hand, a thread-based solution (using JRuby, for example) can maintain a threadpool with hundreds of worker threads because the cost of an additional thread is nearly negligible.