Running an Applescript in KM is EXTREMELY SLOW

Please consider the following macro:

it executed an Apple Script that does some action in Outlook. The script itself is extremely fast, like 0.1s, but triggered by a hot key in Keyboard Maestro it takes like 6s, which makes KM essential unusable in this case.

Why is it so slow? I tested the same with other similar tools, just as ykey on which this would be executed within 0.3s.

What can I do to make KM faster?

I'm running MacOS 10.13.6.

I've not noticed KM being this much slower, but it will always be slower than a direct execution of the script file. Only @peternlewis can change KM to make it faster.

Where speed is important, I'd suggest that you use FastScripts rather than KM.

Have you tried embedding the script in the KM macro, instead of executing it from a script file? Does it also run slow?

Have you tried to launch the script via a Service workflow (or the macOS Script menulet, which should be equivalent)? If it’s faster that way, then simply trigger the Service workflow with KM. There’s an action for that. (“Execute an Automator Workflow”.)

The first question to ask is why is it slow? Keyboard Maestro runs scripts simply by using the shell command osascript to execute them, so you could try in the Terminal running the command:

osascript /path/to/script.scpt

And see if that is fast or slow.

Also, since Macro Groups control when macros are active, rather that the If Then Else you have, you should have a macro group that is targeted at Outlook and place the macro in there, and then just have the single Execute AppleScript action in the macro. Not that that will make the macro run any faster.

Failing all that, you should try to get an Activity Monitor sample of Keyboard Maestro Engine to see what it is doing, since there is clearly no reason it should be taking six seconds to run a trivial script.

1 Like

Thanks for the suggestions!

I tried to run the script from a shell using osascript, and the behaviour was interesting:

  • the first run was pretty slow, a few seconds perhaps
  • the subsequent calls using osascript were executed instantaneously (in 0.1s or so), as if something were now loaded into cache which was not the case before the first run.

The interesting thing is: now that I have executed the Applescript once from within a shell it is even fast in KM. Weird!

Can anyone explain that?

Thanks!

Presumably the system needed to compile something or otherwise write information back to the script that it has now done. I don't know why it wasn't doing it before, maybe something about the slightly different environment in Terminal and Keyboard Maestro Engine (maybe it needed a UI context that it doesn't have in Keyboard Maestro Engine for example).

AppleScript can be rather opaque.

Hello,

I'm reviving this topic to say I have the same issue in the latest version of Keyboard Maestro.

There is a simple AppleScript that the kind members of this forum helped to create some years ago. It basically retrieves the first name from the current chat in Messages. When I execute this script using Typinator, it is blazing fast, but when I embed it in KM, it delays for at least a few seconds.

I believe there is an issue somewhere in Keyboard Maestro that is delaying AppleScript, because the same script works much faster in other apps.

Did you try the advice above:

Specifically,

 osascript /path/to/script.txt

Keyboard Maestro executes scripts via osascript, and it is unlikely there is any delay in Keyboard Maestro handing the script to the osascript tool, but there may be a significant delay in it compiling or executing the script depending on exactly how the script is written.

Peter, you, Chris and I have discussed this a number of times. It is a fact that KM is slower in executing AppleScripts than many other tools, like FastScripts. For the most part I don't notice it, but others who have older/slower Macs often do notice.

Maybe there is another approach KM could take that would be faster?

I would adore it if KM didn't use osascript and created its own AppleScript context. It would allow the creation of NSWindow/NSView/etc. class objects directly from within Keyboard Maestro by way of AppleScript. But I can imagine that achieving this would be no small feat of programming torture, and not something one would be in a rush to jump on.

Keyboard Maestro uses osascript for almost all of its AppleScript access because AppleScript crashes, and any internal AppleScript use would result in the Keyboard Maestro Engine crashing with it.

I could create a whole new application and run it within that, but osascript works fine. Use cases like this where the script is probably being slow because it is recompiling can generally be resolved by pre-compiling the script and running it as a compiled script. But even if not, the consequence of crashing the Keyboard Maestro Engine would not be worth it.

For what it's worth, here is the AppleScript, which was authored by Christopher Stone from these forums:

# Auth: Christopher Stone
# dCre: 2017/02/03 16:24
# dMod: 2017/02/04 18:43
# Appl: Messages & System Events
# Task: Get the Description of the Selected Chat and set text of message field.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @System_Events, @Get, @Description, @Selected, @Chat
-------------------------------------------------------------------------

tell application "System Events"
	tell application process "Messages"
		tell (first window whose subrole is "AXStandardWindow")
			tell splitter group 1
				tell table 1 of scroll area 1
					tell (first row whose selected is true)
						tell UI element 1
							set chatDescription to description
						end tell
					end tell
				end tell
				if first word of chatDescription is "New" then
					set theSalutation to fourth word of chatDescription
				else
					set theSalutation to first word of chatDescription
				end if
			end tell
		end tell
	end tell
end tell

-------------------------------------------------------------------------
}

All it's doing is returning part of the active message's chatDescription from Messages' UI element. I should also mention that I'm running this on an 8-core Xeon 3.3 GHz Mac Pro (2013) with 64 GB RAM and SSDs everywhere, so performance should not be an issue.

There is certainly a noticeable difference in how quickly Typinator produces the result versus Keyboard Maestro.

I'll try executing it from osascript and report back.

I ran this script on my Mac, both in Script Editor and in Keyboard Maestro, as text and script and script bundle and application.

The form of the script did not appear to make much difference to the execution time.

The script took between 0.37 and 0.51 seconds to run, and Keyboard Maestro executing it added about 0.15-0.20 seconds.

Running the script directly in osascript was about 0.05 seconds faster than running it (and various other timing actions) in Keyboard Maestro, so basically about what I would expect.

I hacked some code up to run that script directly within the engine, and as expected the 0.15-0.20 second excess for using osascript dropped to about 0.05 seconds.

So basically that is the cost of using osascript to execute the scripts, about 0.1 to 0.2 seconds of overhead (more on a slower Mac perhaps). For some situations, this is going to be noticeable. but not as noticeable as Keyboard Maestro Engine crashing.

However, it does not explain the apparent behaviour:

When I execute this script using Typinator, it is blazing fast, but when I embed it in KM, it delays for at least a few seconds

In my tests, the script accounted for the bulk of the time (80% or so), and there was at most a 0.2 second overhead. So I have no idea where the “delays for at least a few seconds” is coming from - that would seem to indicate something else going on, like the system deliberately throttling process launching for example.

I have the same issue but I'm just learning AppleScript so I'm not sure if my code makes sense. I want to get the current track name and save it to a variable in KM and display the variable on my Stream Deck. However, it takes a long time to get the result with my script below and that makes it impossible to get live visual feedback. I'm not even really sure if this is the right way to get the track name constantly.

tell application "System Events"
	tell process "Logic Pro X"
		set visible to true
		
		
		if title of window 1 contains "Tracks" then
			return value of attribute "AXDescription" of UI element 1 of UI element 1 of group 4 of list 1 of group 2 of window 1
		else
			if title of window 2 contains "Tracks" then
				return value of attribute "AXDescription" of UI element 1 of UI element 1 of group 4 of list 1 of group 2 of window 2
			else
				
				if title of window 3 contains "Tracks" then
					return value of attribute "AXDescription" of UI element 1 of UI element 1 of group 4 of list 1 of group 2 of window 3
				else
					if title of window 4 contains "Tracks" then
						return value of attribute "AXDescription" of UI element 1 of UI element 1 of group 4 of list 1 of group 2 of window 4
					end if
				end if
			end if
		end if
		
	end tell
end tell

So this is another thread that leads me to think some advice in the wiki on how to run fast would be helpful.

I’m wondering two things:

  • Whether two successive AppleScript steps would run faster or slower than combining them.
  • How to compile an Applescript script and point to it? I’d guess using Script Editor. Could KM itself point to the button to press to compile?

A single script would presumably run faster, since it would avoid the setup time which is likely the entire difference.

In my tests, compiling the script did not make any difference.

2 Likes