> when [MzScheme] wants to find a thread to run, it asks the O/S kernel about each socket in turn to see if any input is ready They've never heard of select()? But really, is there some reason that it's hard to collect up all the fds at once or something?
Read C10K? Both select() and poll() have this problem internally. You have to use one of the more advanced techniques available if you really want to scale. epoll(), kqueue() or friends.
Why HN was slow and how Rtm fixed it
61–70 of 202 posts
Re: Why HN was slow and how Rtm fixed it
#62Earlier quoted context omitted.
not to mention that one thread per connection is, well, extremely outdated.
I don't know much about MzScheme, but it's quite possible that "thread" means "stack", not "OS thread". One context stack per TCP connection is quite sustainable; with Haskell's threads and Perl's coros, I run out of fds long before I'm using any significant amount of memory. (This is somewhere around 30,000 open connections on my un-tweaked Linux desktop. I know I can do a lot more if I tried.) The issue, in the cas…
Re: Why HN was slow and how Rtm fixed it
#63> It turns out there is a hack in FreeBSD, invented by Filo, that causes the O/S not to give a new connection to the server until an entire HTTP request has arrived. This might reduce the number of threads a lot, and thus improve performance; I'll give it a try today or tomorrow. Anyone know if they're referring to "accept filters" here? FreeBSD folks can "man accf_http" if they're curious, which does prevent a reque…
Re: Why HN was slow and how Rtm fixed it
#64Reverse-proxying via nginx would solve this problem and more: the arbitrary 30 second limit on form submission (hotspots sometimes are slow...), nginx could handle rate limiting & logging instead of srv.arc, etc. The Arc codebase would btw be smaller and cleaner (no policy/sanitization code, etc.). Serving static content via Apache was a first step ;-) Don't reinvent the wheel!
Did you just tell people running a company that reinvented funding with their custom written news site written in their own programming language with a custom web server that they shouldn't re-invent the wheel? They think they can build a better wheel. They seem to like doing it and have a habit of it. There's nothing wrong with that.
Re: Why HN was slow and how Rtm fixed it
#65Sounds like there is a scalability issue within MzScheme in that it iterates over the number of threads, asking each thread about the sockets it has. As one can tell, once # of threads and # of sockets grow - finding which thread to run in user space becomes awfully expensive. As any clever admin will do, a least invasive fix involving limiting the number of connections and threads was done - with what sounds like im…
I think this whitepaper covers the plt web server bundled with MzScheme (now 'Racket'): http://www.cs.brown.edu/~sk/Publications/Papers/Published/kh...
Re: Why HN was slow and how Rtm fixed it
#66What is this the 1990s?
Re: Why HN was slow and how Rtm fixed it
#67Re: Why HN was slow and how Rtm fixed it
#68Thanks for the work and it sure seems to be a lot more responsive.
Re: Why HN was slow and how Rtm fixed it
#69Re: Why HN was slow and how Rtm fixed it
#70> when [MzScheme] wants to find a thread to run, it asks the O/S kernel about each socket in turn to see if any input is ready They've never heard of select()? But really, is there some reason that it's hard to collect up all the fds at once or something?
I think in part there is a tendency, among server developers, correctly, to fear anything that looks like a busy wait (e.g., with the name poll). But really poll is just as asynchronous as select in this context (I don't know about FreeBSD's implementation -- but Linux puts to sleep wait queues the same way, afaik). It just doesn't suffer from the crazy indexing scheme of select....
At any rate, I didn't get a chance to finish probing the internals of what mzscheme uses. But if there's a way to substitute poll for select, it can often alleviate those issues of 900 requests queue up and you eventually have an fd with a value of 1024 or greater -- even though you may not have 1024 actual concurrent requests....
Though others feel free to correct me if I'm wrong. I only comment because I came across a similar issue recently. This link may be useful too:
http://www.makelinux.net/ldd3/chp-6-sect-3.shtml
ETA. i finally got a copy of the most recent racket source (though probably not the one rtm and pg are using). but if anyone is curious, browse racket/src/network.c. the source version for mac uses a bunch of selects (e.g., for tcp-accept). replacing with poll might help.... the max number of FDs per login session is often 1024 by default. so you might want to bump that up if it's not already. and consider using poll.... just an idea.