[MonoTouch] Startup times: nib vs. nib-less [was Re: Can I show splash image within a second?]

Rory Blyth lists at rory.me
Fri Nov 27 22:02:32 EST 2009


The fact that performance seems to be better on a 2G (and, as you probably saw, Ed feels the same way you do) is disturbing. Only because I have a 3G. If I didn't have a 3G, I'd think, "Well, this really sucks for people with those garbage 3G models."

But I *do* have a 3G. So, instead, I think, "Drat."

As for posting the code, I'll get it out there. I'm expanding on the tests, and I'm also going to create Objective-C versions just for kicks. This little thread has turned into a peripheral obsession for me (occupying the spot in the back of my head that isn't occupied by all my primary obsessions).

Wow. I almost ended that sentence with a semicolon.

Maybe it's time to take a break from coding...

- Rory Blyth

On Nov 24, 2009, at 5:22 PM, Chris Hardy wrote:

> Hi Rory,
> 
> Great e-mail! I always keep my MainWindow.xib file empty and load in another xib... or I think that's what I'm doing. Some great advice though. 
> 
> Something I've found is that the performance and load up times seem (I've not compared side by side) better on a 2G (1st gen) phone compared to a 3G phone. The 3GS blows them both out of the water but that's neither here or there. I'm not sure if anyone has a 2G laying around - I might blast out some tests though - could you up the code somewhere so we can make sure we've got a base test project?
> 
> Cheers for getting involved, you should pop by the IRC channel more often.
> 
> ChrisNTR
> 
> On 25 Nov 2009, at 00:43, Rory Blyth wrote:
> 
>> [NOTE: This is a pretty long one. Just warning you up front so you don't start reading and then get frustrated when you realize how much scrolling you might have to do to finish it :) ]
>> 
>> For anybody who was following the thread about xib vs. xib-less performance ([MonoTouch] Can I show splash image within a second?), I was telling Akihiro Uehara (apologies if I've mixed first and last names - I don't know if the Japanese custom of referring to strangers by last-name-first carries over into email) to try going sans-xib for a performance gain.
>> 
>> My experience on the Objective-C side of things, as well as according to what I've read, is that there's a performance hit for using xibs. This is especially true if you're trying to stuff your entire app's UI in a single xib.
>> 
>> If you aren't familiar with oddities of xibs/nibs, here are a couple things to know:
>> 
>>     - A xib is just an XML nib (they're for the tools - not for your app's binary)
>> 
>>     - When you build your app, xibs become nibs 
>> 
>>     - When your app runs, a nib's entire contents are loaded into memory
>> 
>> It's this last item that's most important. It's a common n00b mistake to try to stuff an entire app's UI inside a single nib (I'll just call them nibs from here on out). It can hurt performance for desktop apps, so you can imagine what it might do to iPhone apps where you're dealing with circa-1999 laptop resource constraints.
>> 
>> When doing Objective-C work, I've either kept my nibs extremely simple (containing the app window and some top-level navigation bits (nav or tab bar controllers, for example)) or I've shunned them entirely. Not just for performance reasons, but also because I've seen some weird bugs that went away when I ditched a nib and coded the UI by hand (I struggled once for a couple days, partially out of pride, to get my app's single nib to load - it contained the app's tab bar controller - the app crashed and crashed and crashed and only stopped when I dropped the nib and spent the ten minutes to code the tab bar controller by hand - I would've done it sooner, but... I'm a geek... it shouldn't have broken, and I wasn't interested in the reality that it had).
>> 
>> But that's in Objective-C Land.
>> 
>> I wanted to ensure I wasn't giving Akihiro Uehara bad information. He wrote a post [1 - Japanese] [2 - English translation] with a link to a zip of a project he wrote to compare performance of the two methods. In his tests, coding won out over nibs. This made sense to me.
>> 
>> However, as he noted, there were some big differences in performance for the initial run of a series of tests. This also made sense to me. Nothing weird about that.
>> 
>> What didn't make sense was that, for the initial run on the device, startup time was significantly slower for the code-driven UI vs. nib. In subsequent runs, the hand-coded UIs loaded much faster than those from nibs, but... what gives? Does anybody know why the initial run would be faster for the nib UI? Seems odd considering the overhead of having to unarchive the nib and then deal with its contents.
>> 
>> I went and ran my own tests today, though they're a little different. Akihiro Uehara created a single app that had a MainWindow.xib file. The app loads, times the creation of the UI from a nib, and then times the creation of the same UI with code. I wanted to go a step further, so I created two projects - one with the usual MainWindow.xib, and one with no xib at all.
>> 
>> (For the curious, MonoDevelop wouldn't let me clear the "Main interface file" option in the "iPhone Application" section of the project settings - to get rid of it, I deleted the xib file (along with its .cs file), opened the app's .csproj file with a text editor, removed the "MainNibFile" element, saved the file, command-tabbed back over to MonoDevelop, and it worked just fine - the app no longer relied on a startup nib - I also checked the app bundle's info.plist, and it didn't have the entry either, so it looks like MT doesn't try to sneak it in there even if you remove it from the project file. Note that, for this to work, you have to make a couple changes to Main.cs, but that's another story...)
>> 
>> For minimal overhead, I created distribution builds (no debug mumbo-jumbo) and specified the "Link All Assemblies" linker behavior to keep the binaries small.
>> 
>> Functionally, the two apps are identical:
>> 
>>     - App loads
>> 
>>     - Start time is saved in Application.Main (before UIApplication.Main is called)
>> 
>>     - UIApplicationDelegate.FinishedLaunching is called
>> 
>>     - End time is saved
>> 
>>     - TimeSpan is created for EndTime - StartTime
>> 
>>     - Ticks are displayed in a UILabel
>> 
>> Again, where they differ, is that one uses a nib and the other doesn't. The latter has no nib - everything is done by hand (creation of the window, creation of a view, creating and attaching a label to that view).
>> 
>> I ran each app 14 times.
>> 
>> For both apps, the first run was, expectedly, the slowest, and by quite a bit. There was one exception where the nib-based app loaded just as quickly on its first run, but I wasn't able to duplicate that outcome.
>> 
>> This is what I did for both apps (I have an iPhone 3G - the plain old model - no "S"):
>> 
>>     1. Ran the app after sending it to my phone - recorded the ticks
>> 
>>     2. Ran the app three more times - recorded the ticks
>> 
>>     3. Used an app called "FreeMemory" to... well, free memory - did this in case performance might have been impacted by low memory - typically, FreeMemory resulted in the phone going from having 5-20MB of memory free to having 40-50MB free
>> 
>>     4. Ran the app again - recorded the ticks
>> 
>>     5. Ran it two more times - recorded the ticks
>> 
>> Here are the results (again: the time is for startup from Application.Main to the end of UIApplicationDelegate.FinishedLaunching where the ticks are assigned to a label) - I've also converted the ticks to milliseconds for easier reading - I'm also only listing the first seven runs of each app - leaving out the second set because it wasn't that different:
>> 
>>     For the app without a nib:
>> 
>>         1. First run after sending to phone: 12.06ms
>>         2. Second run: 4.7ms
>>         3. Third run: 4.6ms
>>         4. Fourth run: 4.6ms
>> 
>>         5. Fifth run (after clearing memory with "FreeMemory"): 6.6ms
>>         6. Sixth run: 4.6ms
>>         7. Seventh run: 4.6ms
>> 
>>     For the app with a nib:
>> 
>>         1. First run after sending to phone: 4.5ms
>>         2. Second run: 3.6ms
>>         3. Third run: 3.7ms
>>         4. Fourth run: 3.7ms
>> 
>>         5. Fifth run (after clearing memory with "FreeMemory"): 5.9ms
>>         6. Sixth run: 3.6ms
>>         7. Seventh run: 3.7ms
>> 
>> I realize these numbers are from a test I created using apps that might not be representative of "real" iPhone apps, but... you gotta admit: the differences are freaky.
>> 
>> Outside the fourteen runs I recorded, I played around, seeing if I could change the results by deleting the apps, resending them to the phone, running Safari first (to consume resources), freeing memory, not freeing memory, blah blah blah... no matter what, the app with the nib started faster than the app without.
>> 
>> And the difference between the first runs of the no-nib app and the nib app after deployment: 12.06ms vs. 4.5ms (?!)
>> 
>> I'm not putting a ton of weight in this, as I know this is a real slapdash way to conduct performance tests, but for those of you who have wondered about startup performance, I thought this might be of interest.
>> 
>> And while the user isn't going to notice roughly 6ms in startup time on the first run of your app, it's food for thought. I don't know what happens if startup is more complex. Typically, I'd be loading various resources at startup (loading images, loading NSCoding archives, possibly grabbing data from the net). In this test, the entire UI was a window, a view, and a label. That's not especially complex. Startup times might vary considerably when you start including real UIs with view controllers, images, etc.
>> 
>> It's also obvious, as I'm pretty sure everybody already knew, that the biggest bottlenecks in startup aren't anything we can code around, so this information is for those of you who, like me, are a touch insane and want to know about anything that can be done to decrease startup time.
>> 
>> Looking at my tests and looking at Akihiro Uehara's, I think this is likely to yield the best startup performance:
>> 
>>     - Keep the MainWindow.xib file
>>     - Keep it simple
>>     - Limit it to your app's initial screen
>>     - Code everything else by hand
>> 
>> Yeah, it probably won't make that much of a difference. I know. But I already said I'm insane, and I know I'm not the only one here.
>> 
>> Performance aside, I'm curious about why it's faster to start the app with a nib. I'm also wondering if I've been wrong this whole time, and if the docs/books I've read have been misleading (if otherwise correct) - probably gonna run off and write the same tests in Objective-C. 
>> 
>> Anyway, for the other obsessive crazies... I hope this helps and/or was of interest :)
>> 
>> [1 - Akihiro Uehara's post in Japanese] http://d.hatena.ne.jp/feb-hare/20091111/1257905293
>> [2 - English translation of the post] http://tinyurl.com/ycsg7za
>> 
>> 
>> 
>> - Rory Blyth
>> 
>> _______________________________________________
>> MonoTouch mailing list
>> MonoTouch at lists.ximian.com
>> http://lists.ximian.com/mailman/listinfo/monotouch
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/monotouch/attachments/20091127/bcb3b1d7/attachment-0001.html 


More information about the MonoTouch mailing list