Put your content in my pocket

Sometimes it takes awhile to fulfill a promise.

One such pledge was made last century to my good friend Jeffrey (he was only a prince at the time.) I said that I’d love to write something for his fledgling mailing list: A List Apart. This past month, I finally got around to writing that piece: Put Your Content in My Pocket.

If you’re visiting this site for the first time, you might be interested in the original article that prompted our collaboration. I’ve also written some articles that explore some of the problems, performance and less than obvious features on the iPhone. For the hard core geeks, there are also some explorations into the specifications.

So enjoy your visit and please make sure to join in the discussion forum at ALA if you have any questions or concerns about my article. Thanks!

Postscript: I mentioned some nonsense in the article: here it is, the Eric Meyer Memorial iPhone Blocker.

What the iPhone specs don’t tell you…

The iPhone technical specifications mention nothing about how much RAM is included nor how fast the CPU is running. Now that I have a toolchain, it was a simple task to take some code from iPulse to investigate.

Note: Apple has obviously not documented the system level APIs that I’m using to extract this information, so take these numbers with a grain of salt. Personally, I doubt that they would bother to make these low-level functions report erroneous information just to protect some consumer spec sheet, so it’s likely that they’re close if not exact.

First, let’s start off with memory. Calling host_statistics() with HOST_VM_INFO returns a count of the number of memory pages in use (the “vm_stat” tool at the command line does the same thing.) Totaling these counts shows that there are 19,500 pages of memory with each page being 4096 bytes. That’s 78,000 KB or 76.2 MB.

Another way to determine memory size is by calling sysctl() with CTL_HW and HW_PHYSMEM. This results in 121,634,816 bytes or 117 MB being reported for physical memory. Similarly, user memory is reported as 93,605,888 bytes or 89.3 MB—close to the 76.2 MB reported by host_statistics(). These calls are equivalent to using “sysctl hw.physmem” and “sysctl hw.usermem” from the Mac OS X command line.

None of these numbers are the nice round powers of 2 that we’re so accustomed to. I suspect that there is some kind of memory partitioning: something like a graphics chip could be using 11 MB of memory and that combined with the 117 MB of physical memory would bring the RAM total to 128 MB.

Now let’s take a look at the CPU speed. Again, sysctl() is our friend, this time using CTL_HW with HW_CPU_FREQ and HW_BUS_FREQ. The results of our test show that the CPU is specified at 400 Mhz with a bus frequency of 100 Mhz.

There have been various hardware reports that place the ARM chip’s frequency above 600 Mhz. Maybe sysctl() is lying to us, or maybe the CPU is clocked down to give improved battery life. Only Apple knows that for sure.

For those of you who care, the source code used for the tests is available.

MobileTwitterrific

There are two things that I really want on my iPhone: Twitterrific and Frenzic. Last week I started taking care of the first one and am happy to announce a proof-of-concept.

Don’t expect much in terms of usability or elegance. The application only initiates a network connection to Twitter, downloads a timeline feed as XML, and then parses it into a data model. The user name from the model is then displayed in a table view. Sounds pretty simple, right?

Bzzzzt.

It took a lot of head scratching to parse that XML data. NSXMLDocument is hidden in the OfficeImport framework (presumably to handle Office XML files.) The ARM linker can’t see the symbol in the framework, so the document is instantiated with [NSClassFromString(@"NSXMLDocument") alloc]. Many thanks go to Lucas Newman for figuring that one out! Also, there aren’t any XPath methods available, so extracting the information isn’t as easy as with AppKit.

(Do a search for “NOTE:” in the source code for more information on the cause and resolution to these problems.)

It’s pretty clear that the development of a native Twitter client should be done “in the open.” There’s a lot of reverse engineering involved while developing native iPhone applications, so getting more brains involved will result in much quicker development. It will also aid in the development of similar types of network-based applications, such as Ian Baird’s Pownce client. It’s also my hope that this project will spur Brent Simmons into doing something creative :-)

So take a look at MobileTwitterrific, and if you think you can help out, please get in touch via my Gmail account. Thanks!

Hacking quicker

It’s no secret that I’ve started hacking on my iPhone.

And what’s the most frequent thing I use in development? SSH2 to copy new builds onto the phone and view NSLog output from the shell.

And is it a pain to enter your password every frickin’ time? And is it slow to connect? Yes and HELL yes.

But we can make it better.

First, let’s make a public key that’s compatible with SSH2. Using the id_dsa.pub key generated by OpenSSH on Mac OS X, we’d use these commands:

% ssh-keygen -e -f id_dsa.pub > id_dsa_ssh2_aster.pub
% scp id_dsa_ssh2_aster.pub root@192.168.0.100:/var/root/.ssh2

(“aster” is the name of my development machine, where I’m logging into the iPhone from. The “192.168.0.100″ is the IP address of the iPhone on my local network. You may need to create the /var/root/.ssh2 directory on the iPhone first.)

Now, on the iPhone, you need to create a file that tells the SSH2 daemon where to find the public key. In /var/root/.ssh2, create a file named “authorization” with the following contents:

key id_dsa_ssh2_aster.pub

If you login from multiple machines, you’d add a new “key” line for each reference to the public key.

That’s all you need to do to avoid the login prompts. We’re halfway there!

Now for the more annoying thing: delays at login. It’s not because the iPhone is doing something stupid like running Javascript: it’s trying to resolve the client host name. Since the iPhone isn’t running lookupd, that’s kinda hard to do, so all we’re really doing is waiting for a timeout :-(

The simple fix is to turn off the “ResolveClientHostName” feature in the SSH2 daemon. As long as we’re tweaking things, let’s also add “NoDelay” to improve TCP network performance. Open /etc/ssh2/sshd2_config on the iPhone and update the configuration to:

#       ResolveClientHostName           yes
	ResolveClientHostName           no
...
#       NoDelay                         no
        NoDelay                         yes

Now restart the iPhone and watch your blood pressure decline as you continue hacking.

Update: These instructions assume that you are using OpenSSH2, not Dropbear. Installing OpenSSH2 gives you a full suite of tools for communicating with the iPhone.

Benchmarking in your pants

Just how fast is the iPhone?

Let’s run some benchmarks comparing the iPhone to my iMac running Safari 3 on a 1.83 Ghz Intel Core Duo processor:

Test iMac iPhone Slower by
100,000 iterations 0.041 secs. 3.209 secs. 78x
10,000 divisions 0.005 0.413 82x
10,000 sin(x) calls 0.009 0.709 79x
10,000 string allocations 0.010 0.777 78x
10,000 function calls 0.010 0.904 90x

This means that Javascript on the iPhone will take about 80 times longer to run than it does on the desktop. Keep that in mind while you’re writing your Web 2.0 applications.

If you need any more proof of how much slower Javascript is on the phone, take a look at the plotting application I did for C4[1]. Make sure to run it on the phone and the desktop: the performance difference is palpable.

But our benchmarking story doesn’t end there. What kind of performance would we get from a native iPhone application running these same kind of tests?

Thanks to the hard work of many developers congregating at the iPhone Dev Wiki, there is now a toolchain that allows us to create applications that don’t rely on sweet technologies like Javascript.

(Note: use Google if you’re interested in these tools; I’m honoring the request to not link directly.)

That, combined with the talents of Lucas Newman (author of Lights Off and other goodness at Delicious Monster,) resulted in a series of tests written in Objective-C. Here’s the source code: Marbles.zip

Let’s see how Javascript compares to native code running on the iPhone:

Test Native Javascript Slower by
100,000 iterations 0.015 secs. 3.209 secs. 214x
10,000 divisions 0.004 0.413 103x
10,000 sin(x) calls 0.105 0.709 7x
10,000 string allocations 0.085 0.777 9x
10,000 function calls 0.004 0.904 226x

In looking at these numbers, it’s easy to see that there are huge performance wins with native applications: lower function call overhead along with faster iteration and calculation. Even transcendental functions and object allocation sees a 700-900% speed increase.

More reasons for developers to crave a real iPhone SDK.

One thing that’s interesting to note: in the process of writing the Marbles test, Lucas noticed that _objc_msgSend_fpret was an undefined symbol in the ARM runtime libraries (triggered when calling NSDate’s timeIntervalSinceDate: method.) I looked around the libraries on the iPhone and couldn’t find any definitions, nor could a workaround with NSDecimal or NSDecimalNumber be found. Maybe this is one reason why the iPhone SDK isn’t available yet: important stuff is missing.

My guess is that developers just need to be patient. Apple is smart enough to realize that there are major advantages to having third party applications running natively on the iPhone. Not only will these applications be easier to write and faster to run, but they will also add to an ecosystem that makes the iPhone even more attractive to consumers. Apple also realizes that releasing an SDK means having interfaces that don’t change, code that works correctly, and documentation that explains its use.

If you’re a Cocoa developer and haven’t started looking at UIKit, now would be a good time. You have what you need to start experimenting. And you’ll be ready whenever Apple is.