6 ms·
Preforking echo server in Python, inspired by Unicorn-is-Unix
- sant0sk1 17y agoRyanMcGreal must not have taken too much time reading the linked article, because this is NOT Unicorn ported to Python. It is a port of the very simple example server written in Ruby in Ryan Tomayko's article about Unicorn. See: http://news.ycombinator.com/item?id=865306 http://news.ycombinator.com/item?id=865306 At the end of Jacob's post he states that he'll be spending his evening reading Unicorn's source. Not porting it.
- RyanMcGreal 17y agoYou're quite right. I've corrected the title to reflect this.
- pwmanagerdied 17y agoAnyone who knows the standard libraries could do this in a few minutes, this post is clutter. :(
- deleted 17y ago[deleted]
- jrockway 17y agoI'm mostly commenting on this article's linked article, but... Prefork is great if you have about two or three concurrent connections, and if you aren't using a dynamic language like Perl, Python, or Ruby. Otherwise, lightweight threads will serve you better. One problem that people have (had?) with persistent preforked mod_perl apps is that copy-on-write also copies on reads for certain Perl structures. Say you have "my $foo = 42" and then you fork. The Sv associated with $foo is shared. But when the child says "if($foo eq ...)", the Sv is no longer the same; it's changed from an SvIV to a SvPVIV. No more sharing. (Maybe Python and Ruby are more clever here, but they pay a speed price on non-forked applications for this.) Eventually you end up with two completely different memory images for the same app instead of the 1 copy of the parent shared with the child. As for the "about two or three concurrent connections" part, I think you will find that "select" exists for a reason. ("select" is just as much a part of UNIX as "fork", BTW.) If you have a bunch of mostly idle filehandles to read from, select (or rather, its modern replacements) will perform much better than a bunch of forked processes. Imagine you are writing a push messaging server; do you really want one process for each of your 1 million users? No; you want a lightweight thread for each. (Try this sometime; create 1,000,000 lightweight threads. Then create 1,000,000 processes that do nothing. Then note which one requires you to reboot your computer by yanking the power cable.)
- blasdel 17y ago> copy-on-write also copies on reads for certain Perl structures This is perfectly okay! Your scalar variables are a pittance compared to your language's runtime and all the bloaty libraries you've imported. Besides, in most of these instances, your memory footprint would grow (until GC) in single-process usage just the same. > Maybe Python and Ruby are more clever here Python is better about keeping things immutable. Matz's Ruby pisses all over itself, it's fundamentally incapable of sharing any objects copy-on-write: http://news.ycombinator.com/item?id=865364 http://news.ycombinator.com/item?id=865364 > do you really want one process for each of your 1 million users? > No; you want a lightweight thread for each. The hell you don't! Both of those options are the same shit in different costumes. Just because lightweight threads make keeping a stateful execution context for each client tractable on real-world OSes doesn't make it a good idea.
- jrockway 17y agoThis is perfectly okay! Your scalar variables are a pittance compared to your language's runtime and all the bloaty libraries you've imported. Besides, in most of these instances, your memory footprint would grow (until GC) in single-process usage just the same. Theoretically, this might be true, but it doesn't seem to work this way in the real world. Both of those options are the same shit in different costumes. Just because lightweight threads make keeping a stateful execution context for each client tractable on real-world OSes doesn't make it a good idea. I'm not sure what improvement you are offering. Lightweight threads have the space overhead of one structure, and almost no time overhead. (epoll is O(n) over active handles; so in most cases, constant time!)
- blasdel 17y agoI think you massively underestimate the benefit of sharing libraries between processes -- It seems to be perfectly normal in the Rails world to have app processes start at several hundred MB, before a single request! I'm not sure how you think threads work. Of course Lightweight Threads have time overhead -- you still have to schedule them!
- ktharavaad 17y agoIf you want to know more about forking processes vs threading. You should look at TCPServer.py in the standard libary. You can look at the ForkingMixin class and the ThreadingMixin class. A good Python server source code to read is the CherryPY WSGI server. You can read it in the web.py git directory here. http://github.com/webpy/webpy/blob/master/web/wsgiserver/__init__.py http://github.com/webpy/webpy/blob/master/web/wsgiserver/__i...