i’m so full of ideas

Archive for May, 2009

Beta testers wanted

May 14, 2009 1:42 am

My blog traffic has grown exponentially. I am as baffled as anyone that one of my entries is the top google hit for “cocoa task_info”, as an example. Seems like a lot of people found me that way, and at least some of you are now RSS subscribers.

So, perhaps a few of you would like to help me beta-test my almost-finished game? I set up a new subsite for it, here: Hearts Solo. I am especially interested in hearing from people who have iPhone 3G or iPod Touch devices, because I haven’t tested my game on either of those. I got a lot of really good beta testers for the two big releases of my USENET newsreader, so I’m hoping I can do as well this time.

One of my goals for this project is to scare up some new iPhone work. I’m not currently working on anything that’s making me any money. If you need some iPhone or Mac programming done, I’d love to hear from you! allen.brunson@gmail.com

linux: app memory usage

May 10, 2009 5:39 pm

Once upon a time, I wrote a Linux app in C++ that used the database access libs from a well-known corporate database vendor. The app was very important to the employer I wrote it for. It had to run 24 hours a day, seven days a week. Unfortunately, the database access libs leaked like a screen door on a submarine. I did not have the source code for them and the vendor was not responsive to my pleas.

So I set up the app so it could restart itself every few hours, in order to clear its leaks. The app ran inside a script, and when it exited with a certain return value, the script would know to restart it immediately. This worked pretty well for a couple of months. Then I discovered that certain usage patterns would cause the app to completely exhaust its heap in as little as 30 minutes. It crashed, taking a lot of important data down with it.

My next try was a tad more sophisticated. I figured out how to determine how much memory the app was using currently, and it would restart itself when its heap size had grown to about 1.5GB. Now it didn’t matter how long it took for the program to exhaust its heap, it would always restart itself long before that happened.

I had planned to show you source code for getting a Linux app’s resident set size. Seems like a good complement to my earlier blog entry which had code to do the same thing for Apple’s platforms. But it requires a lot of code, due to boring details like file access, string manipulation, and so on. So I’ll just describe the algorithm, and let you implement it yourself, if you’re interested.

Getting a program’s resident set size on Linux involves querying the /proc pseudo-filesystem. First you must create a pretend “filename” that looks like this:

    /proc/(pid)/statm

where (pid) is the pid of your program, which you can get with the posix function getpid(), converted to a textual representation. Open the “file” with whatever file manipulation APIs you normally use. fopen() is a good choice. Read the contents of the pseudo-file with fread(), then close it with fclose(). You should end up with a line of text that looks like this:

    38546 48861 1677 104 0 36313 0

This is a list of various memory statistics about your program. The only one we’re interested in is the second number, 48861 in this example. This is your app’s resident set size, in pages. I’d prefer to have that value in bytes, so you can multiply the number of pages by the memory page size, which you can retrieve by calling getpagesize(). That’s it, now you’ve got a more-or-less accurate count of the number of bytes your Linux program is currently using.

cocoa: app memory usage

May 3, 2009 6:30 pm

My least favorite part of Cocoa programming is its reference-counted memory management scheme. If you can exclusively target Mac OS X 10.5 or later, then you can use garbage collection instead, which is better. But it doesn’t work on Mac OS X 10.4 or earlier or the iPhone, so garbage collection might as well not exist, as far as I’m concerned. Yes, I know Cocoa’s reference-counting scheme has “only a few simple rules” you have to follow … yet Apple’s own apps tend to leak pretty badly. Back when I was using Mac OS X 10.4, I could only run Safari for a few hours before I had to restart it. Seems to be less of a problem in Mac OS X 10.5, but they’re likely using garbage collection these days.

So, early versions of your Cocoa programs are probably going to leak. There are ways to combat this. The primary ones are the leaks command-line tool and the Instruments app that comes bundled with Xcode, neither of which I like very much. I’d prefer that the app itself report its bad behavior. To that end, I’d like my apps to be able to tell how much memory they are using.

Surprisingly, an app’s memory usage is subject to interpretation. Suppose your app and another are both using one in-memory copy of a shared framework. Should your app’s memory total include the size of the framework or not? What if your app has a lot of memory allocated that currently lives on disk in a swap file — should you count that?

I’ve spent some time in the past studying this issue, and I’ve decided to go with a figure called the “resident set size.” This is more-or-less how much memory your app is using. Not perfect, but plenty close enough for my needs. Here’s how you can get it.

#include <mach/mach_init.h> #include <mach/task.h> #include <sys/time.h> #include <sys/resource.h> #include <stdint.h> #include <string.h> #include <unistd.h> int64_t MemoryUsage() {     task_basic_info         info;     kern_return_t           rval = 0;     mach_port_t             task = mach_task_self();     mach_msg_type_number_t  tcnt = TASK_BASIC_INFO_COUNT;     task_info_t             tptr = (task_info_t) &info;         memset(&info, 0, sizeof(info));         rval = task_info(task, TASK_BASIC_INFO, tptr, &tcnt);     if (!(rval == KERN_SUCCESS)) return 0;         return info.resident_size; }

This was difficult to write. It makes use of Darwin kernel APIs, which Google knows almost nothing about.

This works on any version of Mac OS X back to about 10.2, I think. It also works on the iPhone simulator, as well as on actual iPhone hardware. I’ve tried it myself on all these, including my own phone. The fact that this function works unmodified on both Macs and live iPhone hardware is proof positive that the two platforms use very similar kernels.

If you want to use this to detect leaks, you have to track your apps’ memory usage over time. Take a snapshot of your app’s size near the beginning of a run, then put your app through its paces for half an hour or so. Is the app’s memory usage trending up?

In addition to being useful for tracking leaks, I simply appreciate knowing how much memory my apps are using. There’s a definite upper limit on how much RAM you can allocate on an iPhone, and there’s no virtual memory at all. If your iPhone app exhausts all physical memory, it can’t start swapping to disk, it’ll just get killed.

I’ve noticed that the app I’m working on now uses 14MB in the simulator, but only 8MB on real iPhone hardware. Probably because simulator apps are really just modified Mac apps. Windows, views, and other user interface elements on the Mac are no doubt heavier than their iPhone counterparts.