random memes }

2007 and ending needless repetition

The year now is 2007. Time for a bit of a reasoned rant.

Every time I start up Windows, Eclipse, Firefox, or an applet JVM (and wait) - I am struck by the same absurdity. In each case we are repeating the same exact computation as the last startup. The result of the computation is almost always exactly the same. Yet even with a CPU capable of processing BILLIONS of instructions per second ... I still have to wait for the computer.

This is absurd. This is insane. Yet the same sort of ridiculous repetition happens millions (or billions?) of times every day.

Let me put this into context.

Back in the 1970's, folks working with Lisp started seeing painfully long startup times. "Big" Lisp (at the time) might require an entire megabyte of memory (then huge), and the time to load all the bits and pieces into memory was a pain. Someone (I do not know who) realized that repeating the same computation every time at startup was silly. Instead a single "image" of the end result could be saved to disk, and later reloaded in a fraction of the time. The Smalltalk folk came to a similar conclusion around the same time.

Save a result as a single image, and later reload need take only a fraction of the time.

A bit later I worked on low-level code driving hardware for an ancient ancestor of IDE. What struck me then was the speed with which the entire contents of memory could be reloaded - when seeks were minimized. At a 5:1 interleave (best possible on that hardware) you could read or write 87KB/second. The entire current running application could be thrown out of memory (and alter read) in under two seconds - far less than the usual startup time.

Hard disks are wicked fast - then and now - when you don't send the head skipping around the disk.

Skip forward to the present - nearly 30 years later - and people still spend time waiting for computers. This is wrong.

Using the SysInternals Process Explorer, I see that Firefox startup takes about 7 seconds elapsed, performs 4266 reads and 125 writes. Do not know which of the various memory numbers to use, but my guess is the 25.9MB of "private data" most accurately reflects the equivalent size needed if read from a single image. The Firefox EXE and DLLs total about 15MB, so I'd peg the "actual data read size" at somewhere between the two numbers: 15-26MB (a very rough estimate). On the hand, the stored form of a process is likely more compact than the in-memory form. Using 25MB as the equivalent single-image size should be a conservative over-estimate. Loading Eclipse nets about 30 seconds elapsed and a 100MB estimate.

Looks like current generation hard disks take about 13ms to start reading (average seek + latency), then manage 30-60MB/s when reading. If loaded as a single image, that puts the startup time for Firefox at roughly 0.5 to 1 second, and Eclipse at 1.5 to 3 seconds.

Firefox takes 7 seconds to start, and should take 1 second (or less). Eclipse take 30 seconds to start, and should take 3 seconds (or less).

But wait! There is more ... (er, less)

Unix variants have this thing called fork(). Calling fork creates a new process that is an exact copy of the parent. This is brilliantly simple idea, dating back to the 1970's. In the late 1980's the hardware got smart enough to support something called "Copy On Write" (or COW). Before COW forking a 100MB Lisp application meant you ended up with 2 processes needing 200MB of physical memory (quite a problem then!). With COW the two processes used the same physical memory for all pages unchanged since the fork. This both saved memory (a lot!), it also reduced the CPU cost of starting the new process.

Skip forward to the present. On boot, load the Mother Of All VMs (JVM, CLR, or whatever). With a whole universe of classes pre-loaded the entire image might come to ... 50MB? Figure an image load time of about 1 second, plus maybe another second to fiddle with the hardware. The typical Unix boot process invokes a simple script interpreter (/bin/sh or the like), loads dozens or hundreds of scripts, and invokes hundreds of small executables. Embed a decent script interpreter in MOAV (say Javascript) and you can get by with fewer scripts and vastly fewer invoked executables. If starting an application means a fork, and slurping in any extra bits needed - then you could expect sub-second startups as routine.

Quite different from how we do things now - but I would bet there is more than one way we could get there - a bit at a time,