Saturday, April 17, 2010

App Engine is MacApp

I've been spending a lot of time lately digging into Google App Engine and Amazon Web Services.  I'd been thinking of them as equivalents -- the two main competitors in the "scalable hosted computation" market.  However, it dawned on me yesterday that they are not actually members of the same category.  To make an analogy, AWS is like the old Macintosh Toolbox -- the APIs for application development in the original Mac OS.  And App Engine is like MacApp -- an early framework for application development.

From a distance, the Toolbox and MacApp served the same purpose.  Both allowed you to create applications.  Both had facilities for creating windows, menus, and controls, provisions for event handling, and so forth.  However, the styles were very different.  The Toolbox exposed raw capabilities like "retrieve the next input event" and "draw a rectangle at a specified location in a specified window".  It was up to the developer to stitch everything together into a coherent application.  MacApp was an application, fully stitched; the developer simply added components to the framework it provided.

There were good and bad aspects to each approach.  Writing a Toolbox app was a lot of work.  A simple "Hello, World" program that fully implemented the user interface guidelines (About box, File, Edit, and Windows menus, etc.) could be hundreds of lines of code.  But because you were accessing the raw capabilities of the windowing system, and managing control flow yourself, you had a lot of power and flexibility.

MacApp, conversely, made it embarrassingly easy to write a simple program.  "Hello, World" was just a few lines of code.  But it had limitations, especially in the early days.  When a new OS release added a new feature -- say, popup menus -- MacApp didn't always support it right away.  And if you wanted to implement some unusual control flow that didn't fit the MacApp model, you were stuck.  You could only work within the confines of the model MacApp provided.

App Engine has limitations of its own.  A few examples: you can only execute code in response to an incoming HTTP request, and the request must complete within 30 seconds, so there's no way of performing a very long computation.  You can't create threads.  You can't control the amount of RAM available to your process.  (For one of my benchmarks, I want a 256MB array, but in App Engine I can't seem to allocate even a 64MB array without triggering an out-of-memory exception).  [Update: originally I claimed the execution limit was 5 seconds, which Ade pointed out is incorrect.  Google's documentation states that the limit can vary but is "typically around 30 seconds".]

I dislike limitations of this sort, because you never know when you're going to trip over them.  You might decide that App Engine is sufficient for your application, and then while working on version 3 you realize you absolutely need threads for a new feature.  This is a bad situation to be in; you either have to find an (often ugly) workaround, port your entire application to a different platform, or abandon the feature.  So I had been planning to focus on AWS, and indeed I'm using it for my "benchmarking the cloud" project.  (As currently implemented, this project would trip over all of the AWS limitations mentioned above.)

Then, yesterday, I was contemplating a new project.  My eight-year-old son recently asked me to teach him programming.  We've done a bit of this before, using MIT's Scratch -- a simple environment where children drag and drop program elements to create sprite animations and games.  However, the drag-and-drop approach quickly becomes cumbersome.  So this time around, I decided to teach him JavaScript.  I spent 10 minutes writing a static HTML file which contains a <textarea> for code input, a Run button, and a <canvas> for display.  When he clicks the Run button, I eval() his code in a context that defines simple graphics functions like circle(x,y,r).

This worked well, but I wanted to turn it into a server-based site.  It would be nice to have access from any computer, and to save the programs somewhere.  A first version of this might only be a few hours' work.  When I contemplated writing it on AWS, my first reaction was a small inward groan at all the steps involved: I'd have to create a new server instance, configure it properly, give it its own EBS backing volume so AWS can restart it after a machine failure, allocate an Elastic IP address and attach a DNS name to it... on and on.  My understanding of how to configure Fedora, Tomcat, and the other tools involved is still evolving, so if I decide to change my setup I'd have two servers to reconfigure (the programming server and the benchmark server).  Pushing new releases is a hassle; I haven't yet managed to script the process.  And then there's the cost; 8.5 cents an hour is $744/year.

Hosting this on App Engine, conversely, would be a few minutes work.  Launch Eclipse, create a new application, add a few files to it, invoke the Publish to App Engine plugin, and I'm done.  Yes, there would be limitations -- I'm already scheming to work around the lack of threads.  (I want the Run button to send a request to the server, which saves the program and performs a syntax check.  Ideally, the database write and the syntax check would run in parallel.  To accomplish this in App Engine, I'll probably have to send two separate requests from the client.)  But the administrative overhead is so much lower that, for this project, I'll gladly accept the limitations.

So, which is better -- App Engine or AWS?  As is so often the case, the answer is "it depends".  For small projects, App Engine seems like the obvious choice.  For larger projects, it depends on how much you care about flexibility vs. ease of administration.  I would not use App Engine for a really major undertaking, but that leaves a lot of middle ground.

If we look back at desktop applications, eventually the frameworks came to dominate.  OS X uses a framework approach.  Last time I did Windows development, everyone used the MFC framework, or Windows.NET (also a framework).  Newer platforms like Android don't even expose a Toolbox style API.  These frameworks still have limitations, but they're far more powerful than the early versions of MacApp, and the limitations are much less burdensome.  Virtually all desktop applications nowadays are built on some provided framework.

Will hosted computation follow the same trajectory?  I suspect so, but it will take a while to get there.  One place where the desktop analogy breaks down is the ability to escape from the framework.  In MacApp, you could always talk directly to the Toolbox when you had to, which made it safer to adopt in the early days.  In App Engine, there's no equivalent way to escape when you need, say, threads.  App Engine makes simple things simple; AWS makes complex things possible.  Eventually someone will give us both.


  1. Small correction. Requests can take up to 30 seconds according to this:

  2. Oops. Thanks for the correction, I will update the post. Not sure where I got the 5 second figure from.