Perl, AppleScript and Mail.app: Prototyping and Benchmarking #

I am investigating a new product for Mscape, since working on the same thing for six years can get somewhat boring. This would involve exposing Mail.app's mailboxes and messages with an alternative GUI, thus I needed to figure out the best way to get data out of it.

The most direct way would be as a plug-in (a.k.a bundles). However, this seems to be an undocumented (and unsupported) approach that relies on private Mail.app methods. There are several plug-ins that exist in spite of this, and presumably their developers have a vested interest in keeping the reverse-engineered headers up to date, but there is no absolute guarantee that this approach will always work. Furthermore, there appear to be some complications with this approach, licensing-wise. Most of the plug-ins are open source, specifically under the GPL. I'm guessing that this prevents me from grabbing their headers and incorporating them into my (closed-source) product. httpMail appears to be under a BSD license and may thus be more permissive about such things, but it's still a messy thing that I'd rather not deal with.

An alternative approach would be to rely on Mail.app's AppleScript support, which has the advantage of being officially supported by Apple, with the trade-offs of lower performance and less functionality. Since, at least in the prototyping stage, I'll be working with Perl (I don't relish the idea of writing something entirely in AppleScript), I went off on the tangent of investigating the best way to tie these two scripting languages together. The simplest way would be to invoke the osacript program, much in the way that I did for my blogroll generator. However, this has some pretty significant overheads, specifically having to spawn another process and compile the script. Some searching turned up a post benchmarking the various Perl-AppleScript glue mechanisms. The fastest appeared to be the DoAppleScript method from the MacPerl package. However, the post mentioned that Mac::OSA::Simple supported pre-compiled scripts as well, something that was not tested. Using this functionality is very simple; it is simply a matter of using the compile_applescript function, and then later calling the execute() method on the resulting object. Incorporating this in the benchmark gives us the following test results (averaged over three runs):

runscript:       42.83 executions/sec
applescpt:       306.66 executions/sec
osascript:       312.33 executions/sec
doscript:        410.00 executions/sec
applescpt_comp: 1108.67 executions/sec

As it can be seen, the compiled version is by far the faster one (the fast osascript times are deceiving, as the post mentions, in fact its speed is closer to that of runscript). However, the AppleScript snippet that is used for benchmarking is very simple (asking the Finder for the name of the startup disk). Running a more realistic script (that iterates through Mail.app's mailboxes, picks one, and returns the subjects of the 131 messages contained within) gives the following results:

applescpt:      6.35 executions/sec
doscript:       6.63 executions/sec
applescpt_comp: 6.72 executions/sec

The spread is much tighter, and so any method should be satisfactory. However, the pre-compiled, Mac::OSA::Simple, approach is still preferable, since in addition to its slight performance advantage, it also provides some handy methods, like the ability to invoke specific handlers within a script. The only approach that may provide better performance and more flexibility would be to use AppleEvents directly, via Mac::AppleEvents::Simple, but this would be much more tedious, since I would have to build them (the events) by hand.

Post a Comment