Life with Lunchhooks

To content | To menu | To search

iPhone

Entries feed

Wednesday 13 February 2008

How Quickly We Forget

I'm fairly amused to see the claims that people make about the iPhone, in particular the claims about how limited it is as a platform (i.e., how little we can expect from it given how limited its CPU, RAM and storage capabilities are). For example, recently Craig Hockenberry wrote about how difficult the iPhone will be to develop for and said this about its RAM constraints:

There are some very tight limits on memory usage. You’re given approximately 64 MB of space to work with [...]

Is 64MB tight? When we compare an iPhone to the desktop machines of today, it's true that it looks a little pokey—my laptop has 4GB in it, and my desktop machine has even more—but that isn't the question here. The question is whether it ought to be enough for the kind of applications people will want to run on the iPhone and, in the context of Craig's article, whether ordinary developers ought to be able to write applications that run on the iPhone without breaking too much sweat, and whether the familiar and easy-to-use development tools developers have become used to can be reasonably expected to target the iPhone.

I have to defer to Craig's actual experience developing for the iPhone when it comes to describing the situation as it currently is, but there is no reason to suppose that it has to be that way. I'd argue that Cocoa and OS X have a long history, and in that history many of the same tools and libraries we're still using today targetted a much more resource-limited platform.

It's easy to be spoiled by the vast amounts of memory that desktop machines have today, but 64MB isn't peanuts. If we go back to the origins of OS X, NEXTSTEP, we find that it ran with much tighter resource constraints. The base model of the very successful NeXTstation originally had 8MB of RAM and a 105MB hard disk—yes, it actually had less disk space than the iPhone has RAM. True, to install the developer tools you probably wanted the 400MB disk option, and with only 8MB it was fairly quick to start swapping, but if you maxed the machine out—to a “whopping” 32MB of RAM—you could run quite a lot without needing to swap. It's true that NEXTSTEP could swap if it needed to, but applications that needed double the physical RAM of the machine were rare indeed.

As a quick test, I booted up my OpenSTEP 4.2 virtual machine in VMware, where the whole virtual machine only has 64MB of RAM, and started a few applications (the wonderful spreadsheet Quantrix, Lighthouse Design's clone of Lotus Improv, Diagram, which The Omni Group later cloned as OmniGraffle, and Preview opening a large PostScript file). Here is the output from ps:

openstep> ps ugxc
USER       PID  %CPU %MEM VSIZE RSIZE TT STAT  TIME COMMAND
clawpaws   184   0.0 14.1 16.8M 9.01M ?  SW    0:05 WindowServer
clawpaws   186   0.0  2.9 3.58M 1.88M ?  SW    0:00 pbs
clawpaws   189   0.0  1.1 2.56M  704K ?  SW    0:00 appkitServer
clawpaws   190   0.0  3.7 5.79M 2.34M ?  SW    0:00 WM
clawpaws   191   0.0  3.0 6.06M 1.92M ?  SW    0:00 Preferences
clawpaws   206   0.0  4.3 7.83M 2.77M ?  SW    0:00 Diagram
clawpaws   208   0.0  1.8 7.17M 1.18M p1 SW    0:00 tcsh
clawpaws   236   0.0  6.4 8.35M 4.09M ?  SW    0:00 Quantrix
clawpaws   249   0.0  1.1 2.06M  752K p1 T     0:00 ftp
clawpaws   251   0.0  6.0 6.70M 3.86M ?  SW    0:00 Preview

Perhaps you think it isn't fair to compare NeXTSTEP or OPENSTEP to what we have today in OS X, but if so you probably haven't seen or used either of them. It may be technology from more than a decade ago, but it's no Windows 95—Unix is old, too, and many of its basics haven't changed much over the years. Objective-C, Interface Builder and friends were there from day one. Today's Cocoa libraries look and feel very much like their counterparts in OPENSTEP.

Craig also writes:

Guess what? This nightmare will become a reality as soon as you start building your iPhone application. There are no NIBs. None.

I don’t think this is one of those “let’s skip it for version 1.0” design decisions. The process of unarchiving the objects in the NIB takes CPU cycles and memory: both things that are in limited supply on the phone.

I hope that you can see from the above how little water the above argument holds. The iPhone has plenty of CPU power for this task—NEXTSTEP used nibs and ran on a 25 MHz 68040, not a 400 MHz ARM.

But there is something else wrong with this argument, too, namely the idea that it is somehow cheaper to create objects programmatically rather than by decoding an object serialization representation such as a nib file. That's a time/space performance claim that needs to be substantiated with evidence. Very very often, human intuition about what is fast is wrong, because modern machines are complex beasts and things like caches and memory access behavior can make a big difference. The way to know is to run tests and see if the performance difference is actually noticable. But to provide some counter-intuition to anyone who thinks it's obvious that pure code ought to be faster, here's one: compact code interpreting a compact data representation may fit in level one cache, whereas the longhand code to do the same task may not.

So, I don't buy it. I'm not saying that the iPhone SDK will have nibs, but I am saying that I've yet to see a good reason why it couldn't.

Monday 16 July 2007

Storing iPhone apps locally with data URLs

Some people think that you need net access to run web-based applications on your iPhone. Not so. The URL below provides a simple tip calculator (sadly this crappy blogging system doesn't let me do a direct link, which sucks, but you can copy and paste and add it your bookmarks on your computer then sync with your iPhone, and/or make your own page with a direct link). By using a data: URL, the entire page content is all in the URL. If save a bookmark for this URL, you can access this little JavaScript-based app even in airplane mode.

data:text/html;charset=utf-8;base64,PGh0bWw+CjxoZWFkPgo8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGggPSAyNDAiIC8+Cjx0aXRsZT5UaXAgQ2FsY3VsYXRvcjwvdGl0bGU+Cgo8c2NyaXB0PgoKZnVuY3Rpb24gdGlwKGFtb3VudCkgewogICAgcmV0dXJuIHRpcDsKfQoKdmFyIG91dHB1dCA9IG51bGw7CnZhciBwZXJjZW50ID0gMTguNSAvIDEwMDsKdmFyIHJ0aXBfZmFjdG9yID0gMC4yNTsKdmFyIHJ0b3RhbF9mYWN0b3IgPSAxLjAwOwoKZnVuY3Rpb24gd3JpdGVPdXQobGluZSkgewogICBpZiAob3V0cHV0KSB7CiAgICAgIG91dHB1dC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCJiciIpKTsKICAgfSBlbHNlIHsKICAgICAgb3V0cHV0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm91dHB1dEFyZWEiKTsKICAgfQogICBvdXRwdXQuYXBwZW5kQ2hpbGQoZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUobGluZSkpOwp9CgpmdW5jdGlvbiB1cGRhdGUoKQp7CiAgICB2YXIgYW1vdW50ID0gTnVtYmVyKGV2YWwoaW5Gb3JtLm51bS52YWx1ZSkpOwogICAgaWYgKGFtb3VudCA9PSBOYU4pIHsKICAgICAgICB3cml0ZU91dCgnSHVoPycpOwogICAgfQogICAgdmFyIHRpcCAgPSBhbW91bnQgKiBwZXJjZW50OwogICAgdmFyIHJ0aXAgPSBNYXRoLnJvdW5kKHRpcCAvIHJ0aXBfZmFjdG9yKSAqIHJ0aXBfZmFjdG9yOwogICAgd3JpdGVPdXQoJyQnICsgYW1vdW50LnRvRml4ZWQoMikgKyAnICsgJCcgKyBydGlwLnRvRml4ZWQoMikgKyAnID0gJCcgKyAoYW1vdW50K3J0aXApLnRvRml4ZWQoMikpOwogICAgdmFyIHJ0b3RhbCA9IE1hdGgucm91bmQoKGFtb3VudCArIHRpcCkgLyBydG90YWxfZmFjdG9yICsgMC4yNSkgKiBydG90YWxfZmFjdG9yOwogICAgd3JpdGVPdXQoJyQnICsgYW1vdW50LnRvRml4ZWQoMikgKyAnICsgJCcgKyAocnRvdGFsLWFtb3VudCkudG9GaXhlZCgyKSArICcgPSAkJyArIHJ0b3RhbC50b0ZpeGVkKDIpKTsKICAgIAp9CgpmdW5jdGlvbiB6YXAoZmllbGQpIHsKICAgIGlmICghIGZpZWxkLnphcHBlZCApIHsKICAgICAgICBmaWVsZC56YXBwZWQgPSB0cnVlOwogICAgICAgIGZpZWxkLnZhbHVlICA9ICIiOwogICAgfQp9Cgo8L3NjcmlwdD4KCjwvaGVhZD4KPGJvZHk+Cgo8aDE+VGlwIENhbGN1bGF0b3I8L2gxPgoKPHA+CkVudGVyIGFmdGVyLXRheCB0b3RhbDoKPC9wPgo8Zm9ybSBuYW1lPSJpbkZvcm0iIG9uU3VibWl0PSJ1cGRhdGUoKTsgcmV0dXJuIGZhbHNlOyI+CjxpbnB1dCB0eXBlPSJ0ZXh0IiBuYW1lPSJudW0iIG9uRm9jdXM9InphcCh0aGlzKSIgdmFsdWU9IjI0LjM3IiAvPgo8aW5wdXQgbmFtZT0ic3VibWl0IiB0eXBlPSJidXR0b24iIG9uQ2xpY2s9InVwZGF0ZSgpOyIgdmFsdWU9IlRpcCIgLz4KPC9mb3JtPgoKPHAgaWQ9Im91dHB1dEFyZWEiPgo8L3A+Cgo8L2JvZHk+CjwvaHRtbD4=

By putting images inline using data: URLs, you can create pretty rich pages and store them locally. I created a 363,488 byte URL for my home page (complete with images) and it loaded just fine on my iPhone.

Here's a quick Perl one-liner to turn HTML into a data: URL.

perl -0777 -e 'use MIME::Base64; $text = <>; $text = encode_base64($text); $text =~ s/\s+//g; print "data:text/html;charset=utf-8;base64,$text\n";'

By making these links programmatically, you even have an ugly hack to do persistent storage on the iPhone. Just encapsulate your app and its state in its URL.