Will Continuations continue?
I spoke about dynamic language support and JSR292 at JavaOne today. I was quite disappointed that no one asked about continuations.
There are a variety of reasons why we haven’t implemented continuations in the JVM. High on the list: continuations are costly to implement, and they might reek havoc with Java SE security model. These arguments are pragmatic and a tad unsatisfying. If a feature is really important, shouldn’t we just bite the bullet?
I’ve thought about this a bit, and here’s my take on why we really shouldn’t add continuations to the JVM. It’s bound to stir up controversy and annoy people, which is a good reason to post it.
By far he most compelling use case for continuations are continuation-based web servers.
A couple of weeks ago I was embroiled in a rather passionate argument about the relevance of continuation-based web servers at an academic retreat at Dagstuhl, Germany. This is an opportunity for me to write down my thoughts on that topic, as the two are closely linked.
The use case for coninuation-based web servers is simple. I want to book a hotel via the web. The web server asks: where? I say Alaska. I love polar bear rides. The server shows me a list of hotels in Alaska. I pick one, it shows me the details. I decide that maybe Alaska in December is too cold, so I clone the browser window, press back a couple of times, until I’m back to the question: where do you want to go today? This time I answer: Hawaii. I get a list of hotels in Hawaii, and pick one. Now I can compare the two destinations side by side.
Upon reflection, I decide to go to Alaska after all. When will I ever get a chance to go Polar Bear Back riding again? I press the button that says “Book hotel and tickets Now!”. I go to the airport on the designated day. As I walk off the plane into the Honolulu sunshine, I find that my parka is uncomfortably warm.
What happened? The server booked my hotel and tickets, based on the last page I visited - which, as far as it knows, was the Hawaii hotel page. It knows nothing of cloned browser windows and back buttons. When I started asking about Hawaii, it literally forgot about Alaska.
The reason the servers tend to forget in this way is because they only keep one call stack per session. This in turn stems from the fact that HTTP and web browsers were designed for browsing stateless hypertext documents, not for dealing with stateful applications.
Continuations can help here, because they can give us handles for multiple stacks, and allow us to return to different ones at will.
This is wonderful, but it’s important to realize that this use case only matters if you’ve designed your UI to follow the he-said/she-said style typical of traditional web apps designed around HTML. This UI is a regression to the days of time sharing, before the advent of the personal computer and GUIs. It’s forced upon you by HTTP; you’d never design a true GUI application to behave this way.
The other important point is that the future of web apps is going to be different. Ajax is a sign of things to come (though it’s only a symptom, not a real solution - but that is another story). In time, entire applications will be downloaded and provide a full GUI in the context of a single page. The primitive dialog we see today will return to the ash heap of history where it belongs.
Such an application would use a modern GUI to open multiple windows on multiple hotels. It would maintain the state that the server “forgot” in our example in objects in the heap. Rather than relying on the server’s stack to keep track of what location we’re looking at, the window showing us the Alaska hotel will be a view on a model object that represents the hotel being viewed. When you pressed “Buy”, it would pass all the information necessary to complete the transaction onto the server. Consequently, we’ll have no more of a pressing need for continuations than traditional applications have today.
Summary: In the short term, continuation based web servers are very nice. Seaside is the nicest one I’ve seen. But ultimately they are just a phase, and we can already see how we will outgrow that phase. Since continuation-based servers won’t be all that significant in the long term, and given the huge lead times and costs of adding continuations to the JVM, it makes little sense to support them.
Posted at 07:55PM May 18, 2006 by gbracha in Java | Comments[33]
Posted by Jon Nall on May 18, 2006 at 08:46 PM PDT #
Posted by Ron on May 18, 2006 at 09:25 PM PDT #
Backward-only continuation, similar to "setbuf/longjump" in C is much easier, but too easy to become buggy and impossible to debug when got it wrong.
I think you should consider the benefit/cost trade-off carefully.
But, if you choose to do it. Go do a world-class job. It is a cool feature.
Posted by Sin-Yaw Wang on May 18, 2006 at 09:26 PM PDT #
I don't see the point of having continuations in Java. After all you can always run a good Scheme implementation, with continuations, on top of the JVM.
Cheers,
Antonio
Posted by Antonio on May 19, 2006 at 02:48 AM PDT #
I found this modal web server built with Scheme. Does anybody know of any other implementations out there?
Cheers,
Antonio
Posted by Antonio on May 19, 2006 at 02:53 AM PDT #
http://blog.ianbicking.org/constraints-and-continuations.html
In any case, web issues asside, Lua and IO offer nice examples of coroutines usage:
http://www.lua.org/pil/9.html
http://luajit.luaforge.net/coco.html
http://www.iolanguage.com/about/
http://www.dekorte.com/projects/opensource/libPortableCoroutine/
Posted by PA on May 19, 2006 at 03:54 AM PDT #
you mean, applets from the 90s?
Posted by lee on May 19, 2006 at 05:49 AM PDT #
Posted by Eugene Kuleshov on May 19, 2006 at 06:02 AM PDT #
I attended your talk yesterday and thoroughly enjoyed it. Thanks. I wanted to ask precisely the question you raise about continuations, but the line seemed a bit long.
The use case you give here for continuations (and therefore the ultimate rejection of consideration for JVM support) seems a bit limited to me. Yes continuations would be very handy for web UIs, but I agree that this model is of probably limited duration. A use case that I think will be of much more lasting interest (and one that is in line with zeitgeist at Sun) is grid computing.
Many uses of grid/utility computing require one to package up discrete computational units and dispatch them out to the grid to be matched with resources and executed. Currently I do that with object serialization, rmi codebase annotation, and all of the machinery of Jini. Basically, I'm handrolling a continuation when I do this and its a very error prone process (lotsa ClassNotFoundExceptions) for which I would appreciate some JVM help. And I don't think this need is going to go away. In fact, I think it will only grow. (Sun certainly hopes it does as a corporation from what I can gather :^) )
The security issues are a real concern, but it seems that Jini has a reasonable handle on those in its model. There are serious EoD issues with that model, but I'm aware of work going on to address some of these, so it's not a pure greenfield kind of development
One final note that will probably obviate any impact of my comments above... I'm with Corky on tail calls. I'd love to see better support for functional languages in the JVM. I think the ability to do this would be major differentiator between the JVM and CLR
Posted by Van Simmons on May 19, 2006 at 07:39 AM PDT #
Posted by Andy Thompson on May 19, 2006 at 08:06 AM PDT #
Posted by Paul Brown on May 19, 2006 at 12:51 PM PDT #
Oh sure, its just a phase... I've been programming web UIs for close to 10 years, my entire programming career. And the end of 'traditional web apps' is just around the corner, with AJAX as a bell-ringer?
I'll believe it when I see it. I've heard this argument before, you realize... flash, swing applets, ibm's sash, java web-start. Wake me when the revolution has arrived. Until then I'll still be dealing with back-button issues (or buying lots of memory for my continuation based web app) every day. REF: http://en.wikipedia.org/wiki/Betamax to understand that the best technology does not always win.
Zzzzzzzzzz
Also, you don't need continuation support in the language for a continuation-based webserver. Witness Spring Webflow (for better or worse).
Posted by 65.211.178.236 on May 19, 2006 at 02:32 PM PDT #
i) continuations are costly to implement,
ii) they might reek havoc with Java SE security model
ad ii) In "A Tail-Recursive Machine with Stack Inspection" John Clements and Mattheias Felleisen shows that the Java security model, which is based on stack inspection, is compatible with global tail call optimization.
http://www.ccs.neu.edu/scheme/pubs/cf-toplas04.pdf
ad i) Costly in terms of what - money? Can't argue about that.
An important use for the JVM is as a backend for other languages than Java. Compilers for Scheme and ML have to jump through all kind of hoops to achieve proper tail recursion with JVM as backend. Adding tail call support would cut execution times in half.
Posted by Jens Axel Søgaard on May 19, 2006 at 05:19 PM PDT #
Posted by ncruces on May 19, 2006 at 07:49 PM PDT #
Posted by morten on May 20, 2006 at 04:20 AM PDT #
Posted by Axel Rauschmayer on May 20, 2006 at 06:14 AM PDT #
You don't want continuations because of web servers. You want continuations because they are a powerful, elegant abstraction: a low-level language component, not a quick fix for one currently fashionable application.
Sure, you can live without them. Just as you can live without classes. But, just as classes are useful because they provide an elegant abstraction that manages state, continuations (or coroutines or maybe generators) provide an elegant abstraction for managing multiple computations.
So the debate shouldn't be "can I think of some end-use that justifies this?" but "what is the best way to provide this abstraction?". If there are costs, what are they, and how do they vary depending on the abstraction used? At what level should they be implemented? What are the security issues (and can capabilities help?)
Posted by andrew cooke on May 20, 2006 at 07:24 AM PDT #
I totally agree with Bracha that the web server use case isn't compelling in the long run. Cooperative threading isn't (IMO) interesting when a language runtime already provides multi-threading. Iterator conversion is a band-aid for dealing with poorly designed APIs.
Note that my list of use cases is specifically for continuations in all their full glory. There are many other uses of continuations, but they do not demand full continuation semantics. There are simpler mechanisms that are subsets of the continuation concept: continuations > {co-routines,lexical closures} > generators
I have come to the opinion that in practice, lexical closures are sufficiently powerful to handle almost all use cases that continuations could be used for, but they are much simpler, both semantically and with regard to implementation complexity.
Posted by Jason Evans on May 20, 2006 at 07:49 AM PDT #
Regarding Andrew Cooke's:
Regarding Jason's comments:
Cheers,
Antonio
Posted by Antonio on May 20, 2006 at 09:54 AM PDT #
Posted by René Ghosh on May 20, 2006 at 01:22 PM PDT #
Posted by cmars on May 20, 2006 at 03:30 PM PDT #
Posted by Eugene Kuleshov on May 20, 2006 at 07:38 PM PDT #
Posted by ncruces on May 20, 2006 at 09:22 PM PDT #
Well, I didn't mean continuations were only useful for compilers!! ;-)
Anyway yes, final recursion would be a nice-to-have feature. Indeed. The GCC compiler does (did?) a good job detecting tail recursion and transforming that into iterative alternatives. Anyway as you point out (in the bug description) implementing tail-call recursion would mean removing stack-frames, thus generating security issues. :-(
Now, I wonder if the HotSpot optimization could (does?) detect tail-call recursion and could make (makes?) some room for improvement there. I'll try to do some experiments to validate this.
Cheers,
Antonio
Posted by Antonio on May 21, 2006 at 05:44 AM PDT #
> The GCC compiler does (did?) a good job detecting
> tail recursion and transforming that into
> iterative alternatives.
It could do better though:
http://community.schemewiki.org/?gcc-does-no-flow-analysis
Posted by Jens Axel Søgaard on May 21, 2006 at 07:47 AM PDT #
Posted by jp on May 21, 2006 at 08:47 AM PDT #
Posted by ncruces on May 21, 2006 at 10:31 AM PDT #
Posted by Gavin King on May 21, 2006 at 08:37 PM PDT #
Posted by Jamie McCrindle on May 22, 2006 at 07:43 AM PDT #
One more time, with formatting:
Here are another three use cases:
Any time a developer has an ongoing process that they need to either:
they're forced to come up with some kind of server side state engine to do it. the proliferation of these state engines in the wild is a good indication that the need exists for continuations as a language feature.
I may be biased because I'm writing a continuations based BPM engine (bpmscript) but it's only because, after writing both a mobile agent framework and a general purpose server side state engine, it became clear that continuations are the most natural way to solve this kind of problem.
So this is a vote for serializeable continuations support in the JVM.
Posted by Jamie McCrindle on May 22, 2006 at 08:07 AM PDT #
Posted by Jason Orendorff on May 22, 2006 at 02:21 PM PDT #
Posted by David Van Couvering on May 22, 2006 at 03:29 PM PDT #
Posted by Attila Szegedi on May 24, 2006 at 08:24 AM PDT #