Optimizing AppleScript

Discussion in 'Mac Programming' started by stefa.rossi, Jul 15, 2014.

  1. stefa.rossi macrumors newbie

    Jul 15, 2014

    I need to optimize the following AppleScript:
    set out to {}
    tell application "iTunes"
    	set a to tracks of playlist "Mobile"
    	repeat with t in a
    		set l to location of t
    		set p to the POSIX path of l
    		set s to the start of t
    		set f to the finish of t
    		copy {{location:POSIX path of l, start:start of t, finish:finish of t}} to the end of out
    	end repeat
    end tell
    return out
    As you can see, it returns the location, start time and finish time of each track of a playlist.
    It takes ~ 14 seconds to run on my computer. Please let me know if you have any ideas. Thanks! :)
  2. tkermit macrumors 68040


    Feb 20, 2004
    This should run about 3-4 times faster :

    set locationStartAndFinishTimes to {}
    set locationStartAndFinishTimesRef to a reference to locationStartAndFinishTimes
    tell application "iTunes"
    	set thePlaylist to playlist "Mobile"
    	set countOfTracks to count of tracks of thePlaylist
    	repeat with i from 1 to countOfTracks
    		set theTrack to (a reference to track i of thePlaylist)
    		copy {{location:(POSIX path of (get location of theTrack)), start:start of theTrack, finish:finish of theTrack}} to the end of locationStartAndFinishTimesRef
    	end repeat
    end tell
    return contents of locationStartAndFinishTimesRef
    The largest part (by far) of that speedup comes from the first two lines of that code, due to a quirk in the AppleScript runtime:
    Hope that helps!

    You also might enjoy this newly published free app by Shane Stanley , which times how long your script takes to run, in case you plan on experimenting further with this...
  3. stefa.rossi thread starter macrumors newbie

    Jul 15, 2014
    That's amazing, on my computer it takes just 2 seconds to run. Thank you very much!
  4. hhas macrumors regular

    Oct 15, 2007
    Specifically, AppleScript lists have terrible performance characteristics: the time it takes to look up a list item is proportional to the length of the list, instead of constant time as it should be[1]. So it's more accurate to say it will run more efficiently rather than X times faster, since 'X' varies according to list length: the bigger the list, the bigger the time saving the more efficient implementation provides.

    The other way you can improve efficiency is by reducing the number of commands you send to the target application. Object specifiers are actually simple relational queries, not object-oriented references (which can only identify one item at a time), so when talking to a well-implemented application it's often possible to request a whole bunch of values all in one go.


    tell application "iTunes"
        tell every track of playlist "Mobile"
            set theLocations to its location
            set theStarts to its start
            set theFinishes to its finish
        end tell
    end tell
    {theLocations, theStarts, theFinishes}
    That will give you three separate lists which you can then process using a 'repeat with i from 1 to count...' loop. Combined with the ugly but effective hack to make list item lookups constant-time, you should get pretty good performance out of it, even on large playlists.

    (The AppleScript book I co-authored a few years back has a section covering common performance optimizations, not to mention lots of other handy info about AppleScript and application scripting in general. Link in sig.)


    [1] i.e. O(n) instead of O(1), for those familiar with big-O notation. AppleScript lists are O(1) vector arrays, as in most languages, but there's some badly coded safety checking that causes the entire list to be iterated every time you get or set an item, which degrades efficiency to O(n), or linear time.
  5. tkermit macrumors 68040


    Feb 20, 2004
    You’re absolutely right. :eek: And thanks for elaborating on that!

    I always enjoy coming across your AppleScript related posts! This one’s no exception.

Share This Page