I know, I know, at first blush it sounds like a bad idea, but if you let the idea marinate overnight and then sear over red hot mesquite – it ends up being a pretty tasty idea. No that isn’t the sound of vertebrae popping in the background:)
I blame Ryan Simmons. In a comment to my previous post, he innocently asked the question (emphasis mine):
Would it be possible to not comit session state to the stone and use something like Ramons current post on scalling ( http://onsmalltalk.com/programming/smalltalk/seaside/scaling-seaside-more-advanced-load-balancing-and-publishing/ ) to redirect users to the same gem.
Avi Bryant read Ryan’s comment and suggested that running Seaside on GLASS using 1 Session per VM could be a viable technique for avoiding commits.
But, 1 Session per VM?
As I’ve detailed elsewhere, there are good reasons for not using a vm to serve multiple concurrent sessions (without doing a commit per request), but if one were to serve a single session per vm, the good reasons are rendered moot.
With 1 Session per VM, session state does not need to be persisted and voila! no commits due to changes in session state. One should be able to approach the same sort of performance achieved with navigation URLs (i.e., 130 pages/second running on commodity hardware: 2.4Ghz Intel, with 1 dual core cpu, running SUSE Enterprise 10, with 2Gb of ram and 2 disk drives – no raw partitions) while continuing to use rich, stateful Seaside components.
Isn’t 1 Session per VM wasteful?
It depends upon how you look at it. The only thing that might be wasted is memory/swap space. A couple of hundred extra processes on todays hardware is not a big deal unless you are swapping.
If you have 100,000 unique visitors per month and a 10 minute session expiry, you end up needing around 20 sessions. Throw in a fudge factor of 5x and you’re looking at 100 sessions.
100 VMs at 100Mb per VM (tunable) should consume 10Gb of RAM, unless you use mmap (which we do). With mmap, only the memory that is actually used is allocated in RAM. The GemStone/S object manager maps and unmaps chunks of memory on demand so the full 100Mb will only be used if needed and when the memory is no longer needed, it is returned to the system. Without some real benchmarks I can’t tell for sure, but I think it is reasonable to assume that 100 100Mb GemStone vms could run comfortably in 5Gb or less of real memory.
On the flip side, in-vm garbage collection is much cheaper, because only the working set for a single session needs to be swept. When session state for multiple sessions is colocated in the same vm, there is noticeable overhead, so with 1 Session per VM we trade memory for CPU.
Conclusions
We will run some real benchmarks to characterize the tradeoffs between memory, CPU, and commits, but based on back of the envelope calculations it appears that 1 Session per VM is a viable approach for scaling Seaside applications with GemStone/S.
I’m headed to Amsterdam and ESUG on Thursday, but I intend to get busy on this when I get back into Portland in early September, so keep your eyes peeled.
8 comments
Comments feed for this article
September 25, 2008 at 3:21 pm
GLASS Beta Update: GLASS-dkh.122 & GLASS.230-dkh.162 « (gem)Stone Soup
[…] or so since the International Smalltalk Developers Conference, I have been busy working on the Single Session per VM project trying to get to the point were I can validate the approach. It was straightforward to make […]
November 22, 2009 at 4:45 am
Thoughts on smalltalk: SandstoneGOODS
[…] SandstoneGOODS allows to use SandstoneDB and one session per client in squeak seaside, which, some argue, is a very performant way to host Seaside web pages.So, how does it work? get a working copy of […]
November 23, 2009 at 12:11 pm
Ken Treis
What if, instead of using “1 session per VM”, we considered “1 VM per session”? I.e., a particular VM could be the exclusive handler for the sessions it serves (a subset of total active sessions, not just one). This would be more closer to the load balancing scenario that Ramon describes in his post.
You’d have all of the advantages of what you described above (sessions not needing to be committed, but instead saved in local temp space) without extra process overhead from running a gazillion gems.
November 23, 2009 at 1:00 pm
Dale Henrichs
Ken,
If you are talking about a single vm serving multiple sessions then things become sticky.
You can’t abort when starting to handle a request, because another request may be in progress, so a vm can only process a single request at a time.
In order to handle multiple sessions in a single vm without blocking, you have to be much more precise about where you abort and commit … you cannot safely abort when anyone else is in the process of looking at persistent data, because the act of aborting may change that data, this greatly restricts your ability to refresh your view. Commit conflicts become a problem to be reckoned with as well …
You can hit pretty acceptable request rates using the commit/request model. When shooting for rates above 500 requests/second, then you’ve entered the realm, where it may be worth taking a look at application specific transaction handling…
November 23, 2009 at 1:23 pm
Ken Treis
Right now, don’t the FastCGI handlers only process a single request at a time anyway? If each VM handles a single request at a time, does the situation improve?
I admit that I have no idea if this scenario would be any better than the one you proposed in the post… I’m just going off of my experience with other frameworks and thought I’d ask.
I like the sound of 500 requests/second, if you’re hinting that you’re getting there. :) Has performance improved lately, or are you referring to the use of navigation URLs?
November 23, 2009 at 1:35 pm
Dale Henrichs
Ken,
My original port of Seaside (based on Seaside2.6) used the idea that you’d process a single request at a time, but allow more than 1 session to be handled by a vm, but the problem becomes that a single long running request can hog the vm and cause delays for the other sessions … the problem of overloading a single vm with active requests becomes even more pronounced when you only handle a single request at a time … so the approach was abandoned in favor of the commit/request idea. If you can guarantee short response times, then this approach reenters the realm of possible:)
I’ve done benchmarks where I’ve hit 1000 requests/second on 8 cpu hardware with 30g of ram and multiple disk spindles using the 1 commit/request model … no trickery, just throwing hardware at the problem.
Out of curiousity, what kind of request rates are you looking at in your application?
December 4, 2009 at 5:54 pm
Ken Treis
1000/second is incredible. Ours is nowhere near that. Our average is somewhere around 4/second currently, with some spikes up around 15-20. I’m glad to know there’s plenty of room to grow. Our single-core server barely breaks a sweat at that.
This particular application started life as a LAMP app, then became a Rails app, then a Seaside+GLORP app… and now it’s in GLASS. It’s much, much faster than any of its predecessors (some pages that used to take 10+ seconds to generate come up in about 100 ms), and users have already commented on how much more responsive it is.
December 4, 2009 at 6:48 pm
GLASS Beats the Competition « (gem)Stone Soup
[…] "http%3A%2F%2Fgemstonesoup.wordpress.com%2F2009%2F12%2F04%2Fglass-beats-the-competition%2F" } In a comment to the 1 Session per VM: Another Scaling Alternative post, Ken Treis shared the […]