7 ms·
I like Unicorn (Rack HTTP server) because it's Unix
- blasdel 17y agofork() in Ruby would be much better if MRI's garbage collector wasn't so awful -- because it marks every reachable object in each collection cycle, it's impossible for MRI processes to take advantage of the kernel's copy-on-write memory sharing post-fork. You can't even just let the processes gobble up space and let the kernel's VM sort it out -- anything that gets swapped out will have to be paged back in to be marked by the GC. Churn.
- jwinter 17y agoRight, that's exactly what Ruby EE was written to solve. Would've been nice for that to land in Ruby 1.9, but at least REE exists.
- defunkt 17y agoBut if you're already taking that memory hit with separate processes, ala mongrel cluster, fork() still provides a number of juicy advantages (which the article explains).
- pdubroy 17y agoI'm not familiar with the MRI source, but in most collectors, I'd think that switching from marking the object directly to using a separate mark map should be pretty trivial (like an afternoon's work). You'd still have to copy the pages for the mark map as soon as you GC in the child process, but that's only 3% of your total heap size.
- steveklabnik 17y agoThe thing is, (from what I understand) Matz isn't interested in performance, he's interested in the language. This is why YARV is Ruby 1.9. So even if it took an afternoon, there'd be no reason to use it, as MRI is the past anyway. (and for those of us still using 1.8.x, there's REE)
- boulderdash 17y agoalmost all GCs are awful
- boulderdash 17y agoactually, in this day and age... if you hit disk for paging/swap on a production server... "you are doing it wrong"... this should not be an issue
- stcredzero 17y agoalmost all GCs are awful Wrong -- almost all of the most visible GCs in the most popular languages are either 1) still awful or 2) were formerly awful for such a long time, they're still living it down. It's a vicious cycle. - GCs have a bad rep. - Precocious programmer implementes their own dynamic language. - They settle for Mark/Sweep or ref counts to "get it done" (Hey, GCs are all awful anyhow, yeah?) - Many people experience the awfulness. - GCs have a bad rep -- REPEAT Chicken & egg? GCs were bad. Experts have since figured out how to make them good. The programmer culture in general is slowly getting this knowledge by diffusion. The VisualWorks GC is so good, as a lark, I once put an infinite loop into the app I was working on that did nothing but instantiate new objects. I could barely tell it was there!
- boulderdash 17y agoso the 'almost all' in my above is wrong? you basically said what I said, but with your favorite smalltalk GC.
- stcredzero 17y agoYes, the GCs you've heard of constitutes an encyclopedic listing of them. </sarcasm> Hmmm, you just gave me an idea. Interview question to see if prospect knows what he doesn't know. Does she/he even have the order of magnitude right on that?
- dschobel 17y agoThreads are out. You can use processes, or async/events, or both processes and async/events, but definitely not threads. Threads are out. Can anyone expound on this? Because the author certainly doesn't.
- wmf 17y agoIt's not clear whether he's saying that threads are bad in Ruby, which is true because of the GIL, or that threads are bad in general, which is just unfounded bashing.
- defunkt 17y agoIt's not just the GIL. Check out Joe Damato and Aman Gupta's awesome presentation from this year's Hoedown for more info on concurrency in Ruby: http://timetobleed.com/ruby-hoedown-slides/ http://timetobleed.com/ruby-hoedown-slides/
- ryah 17y ago> which is just unfounded bashing. i'm always surprised to hear things like this. it's certainly not unfounded - it's just so obvious and universally accepted that it doesn't require explanation - one would think.
- dschobel 17y agoI think it may be obvious to people with a c/++ background, but when I was in school in the early 2000's, they taught you concurrent programming in Java via threads. And the concurrency primitives and frameworks in languages like Java and C# are so easy to use there's a whole generation of us who think that threading is the easy way to do concurrency.
- jshen 17y agothreading is not easy in java. Check out http://www.javaconcurrencyinpractice.com/ http://www.javaconcurrencyinpractice.com/
- colbyolson 17y agoI don't know much about Ruby or 'threads vs processes', but his blog sure is refreshing and simple!
- mbrubeck 17y agoHere's his writeup of his blog design: http://tomayko.com/writings/administrative-debris http://tomayko.com/writings/administrative-debris
- cschneid 17y agoAt least last time I checked, he was running a custom written blog engine that several of us in #sinatra made a bit more generic. It's probably been heavily modified or even replaced since then. Link: http://github.com/rtomayko/wink http://github.com/rtomayko/wink
- mrshoe 17y agoThere's a good reason most Ruby and Python projects don't rely heavily on system calls: portability. If you care at all about portability, it's just easier to not hit the system calls directly, otherwise you'll have to detect host OS and make sure you're using the system calls properly. If threads are "out", then pre-fork is way out. Just look at the history of the Apache project. I realize this all happened before the RoR era, but Apache used to use a pre-fork MPM almost exclusively. In more recent years it has added the threaded MPM and the async MPM. They have also put in the work I mentioned above to achieve cross-platform compatibility. I'm just using Apache as an example here; I'm not suggesting that we should all use Apache. It's just funny to me to see a post that basically says, "All the stuff we've been doing for the last 5 years is out. We should be doing the same stuff they were doing 15 years ago, but in Ruby this time around instead of C." Maybe software trends are like music trends? Everything from 5 years ago is lame, but the stuff from 20 years ago is super groovy, man.
- defunkt 17y agoCounter example: nginx, which uses fork(), and seems to smoke Apache while offering features like binary reloading without dropping connections (not sure if Apache supports this but I seem to remember no - please correct me if I'm wrong). Portability is not always necessary - when talking about fork() and friends you're talking about trade offs. When I'm only ever deploying to Unix environments, I accept the lack of portability in exchange for features I value.
- mrshoe 17y agoThat's not really a counter example. nginx does indeed fork off child processes, but it uses async I/O in each child process. It doesn't use the traditional pre-fork process-per-connection model that Apache's pre-fork MPM uses or that Unicorn is using.
- defunkt 17y agonginx relies heavily on system calls at the expense of portability.
- blasdel 17y agoJakob Kaplan-Moss thought it’d be an interesting exercise to port Ryan’s code to Python: http://jacobian.org/writing/python-is-unix/ http://jacobian.org/writing/python-is-unix/
- jherdman 17y agoThat's fine and dandy, but when I want to use your libraries with JRuby or MacRuby, I'm SOL. I kind of like the portability of avoiding fork() and exec() for those reasons.
- jeremymcanally 17y agoWell, it's a Rack web server. Just use one that works on those, problem solved. That's the whole point of Rack.
- jherdman 17y agoPoint taken. In the general case, though, (i.e. we're talking about more than Rack awesomeness) I think it's important that people keep this in the back of their minds. I was burned on this recently with the use of the Daemon Kit gem in a project. It's definitely a "do-better" on my part to more closely examine the libs I'm working with, but as an author in a language wherein numerous OSes and implementations of the interpreter are used, it's something to keep in the back of your mind as well.
- gsiener 17y agoWhy didn't they use Twisted?
- oldmoe 17y agoGood question, may be even build on Tornado, though it seems that Unicorn is written in Ruby.
- wsprague 17y agoThe master has passed away, but here is the real deal (tm) in Unix: http://www.kohala.com/start/ http://www.kohala.com/start/ There is nothing more I can say -- I am so in awe...
- josephruscio 17y agoThis book (http://www.unpbook.com http://www.unpbook.com) and this book (http://www.kohala.com/start/apue.html http://www.kohala.com/start/apue.html) are both very good. Not to mention keeping abreast of new stuff in the Linux Kernel at http://www.lwn.net http://www.lwn.net or http://kernelnewbies.org/LinuxChanges http://kernelnewbies.org/LinuxChanges. As productive as dynamic languages make us, I think we sometimes forget that this is all typically built on Linux/C, and that's not changing anytime soon. A _good_ hacker should at least have a basic knowledge of what's under the hood.
- yesimahuman 17y agoAnother good book: http://www.advancedlinuxprogramming.com/ http://www.advancedlinuxprogramming.com/
- jsrn 17y ago> [...] and this book (http://www.kohala.com/start/apue.html http://www.kohala.com/start/apue.html) > are both very good. this refers to the first edition of APUE - there is also a very good (IMHO) second edition co-authored by S. Rago (a former collegue of W. Richard Stevens): http://apuebook.com/ http://apuebook.com/ (first edition: 1992, second edition: 2005) The second edition mainly adds better coverage of POSIX (much of which was developed after the first edition was published) and current UNIX variants (Linux, FreeBSD, Solaris, MacOS X) while leaving out obsolete stuff.
- josephruscio 17y agoThanks! Rago is the copy I actually have on my bookshelf, didn't notice the site I linked was only the first edition. Guess with Steven's unfortunate passing they made a new site.
- boulderdash 17y agoWhen I read stuff like this, I should go... Yay, they are back on the path. However, I'm stuck on the... why are they even off the path in the first place? Why should rediscovery of processes and the 'select' call be news? ... I should just write a big blog post about this ... (which I'll never do... to busy working :-)
- kmavm 17y agoI'm sorry I'm coming to this with the thread dead. I was on a boat for a team-building offsite most of yesterday. People also overlook the great benefit of fork(2) for static languages: it's like GC for your address space. In a long-enough-lived multi-threaded C/C++ program, heap fragmentation will eventually eat you just as badly as a memory leak would have. Since there's no GC to compact the heap, the only real solution for memory-intensive servers is scheduled restarts. A good, old-fashioned fork(2) resets the address space to a known-ok state; after the client connection is done with, whatever fragmentation the request has introduced disappears with its container process. The canonical, ancient structure of UNIX servers (fork after accept) was what enabled those servers to stay up for months and years at a time, but very few people made that connection. When processes were the only concurrency primitive available, we saw only their costs, and assumed threads would be better, since their costs were lower. In some ways, processes were the devil we knew, and threads an unfamiliar devil; in addition to all the usual complaints (e.g., about how hard it is to synchronize), threads mean that the global heap lives forever.