Pre-Load AppleScript-ObjC Bridging Files in AppleScript Script Runners

Background:

AppleScript's capabilities are greatly enhanced by being able to call Objective-C methods with AppleScript-ObjC (ASObjC/ASOC).

When the OSA scripting component instance executes (not imports) the first line of ASOC code, it has to load the bridging files that enable ASOC interoperability. This can take upwards of 0.5–1.0 seconds on some systems.

Subsequent AppleScript runs that re-use the same scripting component instance (even on different files) do not need to re-load these bridging files, so execution is much faster (almost instantaneous on simple scripts).

BTT:

BTT now has great support for AppleScript.

From what I can tell, BTT uses a separate process as a script runner to run AppleScripts, and re-uses it for future script runs (which is perfect). This means that the above behaviour is readily observed (the first run of an ASOC script in the helper process takes much longer, but subsequent runs are much faster).

Feature Request:

BTT's AppleScript-running processes can be "primed" after creation by running a short AppleScript that executes a couple of throwaway ASOC calls.

An example AppleScript that would accomplish this is:

use framework "Foundation"
use framework "AppKit"
current application's NSString's |string|()
current application's NSWorkspace's sharedWorkspace()
return

(This bridging files are loaded by the code in lines 3 & 4, not the "use" statements themselves.)

FastScripts 3 did a similar optimization that proved very effective (reference).

Andreas, I'm hoping this is something you could implement, since it would make ASOC execution times reliable (and fast enough for more use cases).

Please let me know if I can provide any other info!

i would recommend to run your priming script when BTT launches via the „BetterTouchTool did launch on specific machine“ trigger.
I think not all systems will need the bridge loaded - it probably adds quite a bit to the memory consumption

Thanks for getting back to me Andreas.

I did think of this initially, but it would rely on knowning how BTT manages its script helpers in great detail – I'm assuming there's more than one instance of the script runner, and there's of course no way for the user to specify which instance of the helper script BTT uses when triggering an action.

For the last couple of years, I've been triggering my AppleScripts through BTT & using a convoluted workaround** to have FastScripts run the AppleScripts – all to avoid this delay.

(**The BTT action runs a shell script, which calls osascript, which sends an Apple Event to FastScripts, which runs the AppleScript.)

I don't believe the bridging files actually take up that much memory.

I haven't run any proper memory profiling tools, but running the above script via osascript in Terminal & inspecting with Activity Manager shows that its process is allocated 14.6 MB vs. 4.1 MB for a non-ASOC equivalent script.

So, it looks like it would take about 10 MB of extra memory. I don't know if you'd consider that significant or not.

Most likely it's more than that - while the BTT processes will only have minimal overhead in memory consumption this triggers the load of various system frameworks in other processes. It's hard to profile though.

I'll check whether I can add an advanced option to trigger this for every script runner, but I think I won't make it the default, at least for now.

(Most of the time BTT only uses one script runner, it's just for stuff that is calling into BTT where two or maybe three are needed.)

Sounds great! Thank you.