How Frequently is Pause Until Tested?

If I'm using a test like this:

image

... how frequently is the condition retested? Once every second?

Is is possible that having dozens of such tests all running at the same time could slow things down? Should I write my own loop that tests every 10 seconds instead?

It is possible but not very likely given that Pause Until has this setting to reduce the CPU burden (shown off here):

image

I don't think anything one can "write" using a collection of KM actions would be more efficient than something built into KM in the first place.

I may be wrong...

BTW, the calculation you're using will always be non-zero except when UPTIME() is exactly 90.

I think the test you should use is UPTIME() > 90

I understand your rationale. I'm trying to come up with a counter-example, but cannot. However it should be possible to rewrite the macro to "trigger" once per second instead of pausing in some sort of loop. But even so, I doubt if that would make much difference.

It might be worth knowing how exactly the "Reduce CPU usage" works. I thought that I read a post which said that it "tapers off" execution after different durations (1 min, 5 min, etc.)

Before I posted earlier I searched for more info on that without success and then continued on the basis of what should be common sense. But I can't honestly say that @August's idea is without merit until he tries it :smile:

He should probably try it with a more computationally heavy operation than a simple math test, perhaps something like this:

image

And he would probably have to conduct this test over a long period of time, while logging the CPU usage over that time frame. Not easy. But he's an experimenter and a hard worker.

You're probably right, but here's a very simple test I left running on my computer while heading to the gym:

Tester macro

Pause Until — How Frequently does it evaluate (with reduce CPU usage enabled).kmmacros (22 KB)

And heres the resulting data from my test:

Test completed in 88:35 minutes

Pause_______"Error"_______CPU
1 ms_______2 ms_______72.9%
1 ms_______2 ms_______109.2%
1 ms_______2 ms_______107.9%
1 ms_______2 ms_______108.9%
1 ms_______2 ms_______91.5%
2 ms_______21 ms_______98.3%
2 ms_______22 ms_______79.8%
2 ms_______22 ms_______81%
2 ms_______1 ms_______81%
2 ms_______22 ms_______128.1%
4 ms_______19 ms_______102.5%
4 ms_______20 ms_______100.8%
4 ms_______20 ms_______85%
4 ms_______20 ms_______73.4%
4 ms_______20 ms_______67.6%
8 ms_______15 ms_______66.7%
8 ms_______16 ms_______61.2%
8 ms_______16 ms_______61%
8 ms_______16 ms_______60.5%
8 ms_______1 ms_______51.4%
16 ms_______7 ms_______47%
16 ms_______8 ms_______41.3%
16 ms_______8 ms_______45.6%
16 ms_______8 ms_______46.1%
16 ms_______8 ms_______60.9%
32 ms_______12 ms_______56.6%
32 ms_______13 ms_______60.7%
32 ms_______13 ms_______54.3%
32 ms_______13 ms_______48.4%
32 ms_______13 ms_______43.5%
64 ms_______1 ms_______38.5%
64 ms_______2 ms_______34.8%
64 ms_______2 ms_______37.8%
64 ms_______2 ms_______44.9%
64 ms_______2 ms_______47.8%
128 ms_______21 ms_______45.3%
128 ms_______2 ms_______36.8%
128 ms_______22 ms_______30.2%
128 ms_______1 ms_______40.6%
128 ms_______15 ms_______96.5%
256 ms_______19 ms_______54.9%
256 ms_______20 ms_______73.1%
256 ms_______20 ms_______59.3%
256 ms_______20 ms_______138.5%
256 ms_______20 ms_______150.1%
512 ms_______15 ms_______78.6%
512 ms_______16 ms_______47.2%
512 ms_______16 ms_______31.1%
512 ms_______16 ms_______69.8%
512 ms_______16 ms_______46%
1024 ms_______7 ms_______64.1%
1024 ms_______8 ms_______74.8%
1024 ms_______8 ms_______67.2%
1024 ms_______7 ms_______158.1%
1024 ms_______16 ms_______119.8%
2048 ms_______12 ms_______45.6%
2048 ms_______18 ms_______153.8%
2048 ms_______6 ms_______30.5%
2048 ms_______16 ms_______32.4%
2048 ms_______11 ms_______53.4%
4096 ms_______6 ms_______39.4%
4096 ms_______5 ms_______45.3%
4096 ms_______11 ms_______37.5%
4096 ms_______2 ms_______31.3%
4096 ms_______8 ms_______31.8%
8192 ms_______21 ms_______108.6%
8192 ms_______12 ms_______37.3%
8192 ms_______2 ms_______33.1%
8192 ms_______11 ms_______119.9%
8192 ms_______9 ms_______33%
16384 ms_______134 ms_______32.3%
16384 ms_______140 ms_______34.1%
16384 ms_______146 ms_______106.8%
16384 ms_______155 ms_______69.2%
16384 ms_______149 ms_______57%
32768 ms_______297 ms_______28.5%
32768 ms_______290 ms_______35.6%
32768 ms_______294 ms_______32.6%
32768 ms_______280 ms_______35.3%
32768 ms_______288 ms_______27.1%
65536 ms_______4574 ms_______29.2%
65536 ms_______4586 ms_______40.9%
65536 ms_______4589 ms_______37.1%
65536 ms_______4595 ms_______39.1%
65536 ms_______4586 ms_______34.2%
131072 ms_______4062 ms_______73.4%
131072 ms_______4064 ms_______34.6%
131072 ms_______4063 ms_______42.1%
131072 ms_______4064 ms_______31.3%
131072 ms_______4060 ms_______33.4%
262144 ms_______304 ms_______38.7%
262144 ms_______3016 ms_______42.1%
262144 ms_______3018 ms_______33.1%
262144 ms_______3016 ms_______100%
262144 ms_______3023 ms_______126.6%
524288 ms_______929 ms_______30%
524288 ms_______932 ms_______120.1%
524288 ms_______951 ms_______39%
524288 ms_______939 ms_______36.5%
524288 ms_______922 ms_______45.5%

Nothing conclusive (of course, the way this test is set up), but the data seems to indicate that the Pause Until (with reduce CPU usage enabled) slows down evaluation frequency after about 10 seconds of reevaluating the conditions, and then again even more so after about a minute.

Great work. I wish KM had some built-in charting actions for situations like this.

OOPS! Thanks! Fingers sometimes don't match my brain.

1 Like

Thanks @tiffle, that's what I needed to know. I'll keep that setting on and not worry about it. I only expect to have at most a couple of dozen running at once, waiting for bootup processes to complete.

1 Like

Test it and see? Maybe with Activity Monitor open as well?

Here's a macro that'll spawn 20 "Pause until..." macros that replicate yours, run the system_profiler shell command, kill all the "Pause until..." macros, run the shell command again. There's a "beep" halfway through if you want to check the KM menu bar item to see the pauses are running (before the beep) or cancelled (after).

Warning: This will kill all your running macros!

Pause test.kmmacros (7.8 KB)

Image

Results for 5 runs:

So anything from 7 seconds (~15%) slower to > 1 second faster with pauses, suggesting that there's a small slow down but that other background activity is just as important. This is with "Reduce CPU Usage" off and the un-paused shell script done second so it would benefit from any cacheing, so the un-paused section has every advantage.

I suspect that you'll see even less impact in real world use, especially if this is for your startup macro where the pauses will impact CPU use but most of your macro's actions (launching apps) are I/O bound and any CPU use is probably on other cores anyway.

2 Likes

Nice to see all the tests on the "Reduce CPU Usage" in the Pause Action. I would love to see what this is actually doing documented in the Pause Action Wiki if that is possible.
https://wiki.keyboardmaestro.com/action/Pause_Until

The only thing I could find on the Wiki is that this setting has been added to the action.
https://wiki.keyboardmaestro.com/manual/Whats_New?s[]=reduce&s[]=cpu&s[]=usage

Why? Would it make a difference in how you write your macros? Do you need more than the "it checks rapidly at first, slows down after 10 seconds, slows a lot more after 60" that's on the Wiki page?

I suspect that the actual gap between checks will depend on a whole lot of stuff -- particularly the check itself. So this:

image

...takes a lot longer than this:

image

...for a single check.

Don't get me wrong, I love to dig into this stuff, but there's plenty on the Wiki already without including esoteric information that doesn't actually help.

2 Likes

I searched the page you and I both listed and not sure where you see that.

Google search

Update: Completely missed that and just found it!
"By default (v11.0+) Keyboard Maestro will start to conserve CPU usage of this action if it runs for a long time (after 10 seconds it will conserve a little, after 60 seconds it will conserve a lot) by only checking the condition periodically. You can turn off this feature in the action (gear) :gear: menu."

I guess what this is saying is it doesn't check as often. I have no idea how often it even checks in the first place but that is cool. I guess that's eneough info though I am still curious.

  1. Open the wiki
  2. Type "pause until" in the search field
  3. Click the suggestion "pause until action"
  4. Read these first sentences...
    By default (v11.0+) Keyboard Maestro will start to conserve CPU usage of this action if it runs for a long time (after 10 seconds it will conserve a little, after 60 seconds it will conserve a lot) by only checking the condition periodically. You can turn off this feature in the action (gear) :gear: menu.

Then find out! Write yourself a macro that logs MILLISECONDS(), does a "Pause Until", logs MILLISECONDS() again, then finds the difference. That's how I know that the two pauses above have a huge difference in execution time, even when the condition is true before the action even starts.

Have some fun baselining how long a single, simple, action takes. On my machine that's ~2 milliseconds. If that's correct then the maximum rate of check is once every ~2ms, since you're effectively repeating the same action over and over again.

Now run 10 concurrent instances of the same speed-check macro. If your results are anything like mine then the Engine's CPU usage will increase 10-fold but the time taken doesn't change. So it isn't that "an action takes ~2ms", it's that "a macro is only revisited, and the next action executed, every ~2ms" -- plus, of course, the time it takes for the action to complete (unless it's async).

Now work out a way to log times with a pause that lasts for 10 (but less than 60) seconds. Do the same but >60s. Estimate how much throttling takes place. Wonder if a reduced rate of checking actually makes any difference at all to your real world use. And realise that, if it does, all you have to do is flick the switch on "Reduce CPU Usage" and spend CPU cycles to get increased reaction speed.

1 Like

OK, here's a couple of demos. None of the results should be taken as absolutes, but will indicate the effect of "Reduce CPU Usage" as a "Pause Until" action's delay extends past 10, then 60, seconds.

"Image Detect Pause" is to demonstrate the impact on CPU usage, relies on an image that isn't on your screen, and the result will be more obvious the more screen real estate you have. Open Activity Monitor, filter on "Keyboard Maestro Engine", select the "CPU" pane, and set the "Update Frequency" (View menu) to "Very often (1 sec)".

Run the macro and watch the Engine's CPU usage over the first 10 second, after 10 seconds, and after 60 seconds. You'll have manually cancel the macro after that :wink:

"Master" is to demo how the frequency of checking changes. A simple "key down" check takes little CPU (as you'll see if you left Activity Monitor open) so the delay in reacting to the key being pressed will indicate how often the check is being made. "Master" spawns 3 async instances of "Pause Macro", each with their own pause before the "Pause Until" action, then simulates the key press 60 seconds later. Eventually it'll display the (approximate) delay in microseconds between the key being pressed and each macro responding to that.

Again, these numbers should be regarded as indicative rather than absolute. Every action takes time -- including the one that's getting the time! -- machine speeds vary, other things going on (particularly other macros) will have an impact. Run it a few times and you'll get some averages for your particular situation.

My results suggest that, on this 2020 iMac with 3.6GHz Intel i5, checking frequency is ~100/s at first, drops to ~20/s after 10s, and is only once every 3 seconds after a minute...

Enough! The macros:

Pause Test Macros.kmmacros (24.5 KB)

3 Likes

Oh wow and thank you. I did some tests after your first post and had typed a reply but I think I wanted to test one more thing before coming back. That is very cool what you put together and certainly taught me some things about Keyboard Maestro in how to run things. I am pretty slowly starting to get my head wrapped around more variables, and calulations using Keyboard Maestro. It's been exciting to learn new tricks. Thank you for sharing that and interesting results to wrap my head around.

Screenshot 2024-12-18 at 4.29.44 PM
Screenshot 2024-12-18 at 4.29.47 PM

Folks seem to have figured everything out already, but some comments.

  • Your action can only increase the CPU usage for the first 90 seconds after boot, so whatever CPU use it might use is going to be completely irrelevant long term.
  • Periodic triggers are much better than any pause action - Keyboard Maestro is designed to use virtually no CPU while no macros are running regardless of what triggers are active (and presuming the editor itself isn't asking for information). Once you are running a macro, the philosophy behind Keyboard Maestro is generally to get the thing you want done, done, not conserve CPU.
  • Your macro could, for example, be written with an Engine Launch or Login trigger that enables the macro, which has a periodic trigger (say 5 or 10 seconds), which checks the UPTIME function and if sufficient, does its thing and then disables the macro. This would be very efficient, but again, almost certainly pointless in this case.
  • A calculation like that shown would likely result in an imperceptible use of CPU more than just a Pause running. If the condition itself was expensive to calculate, that is what the Reduce CPU Usage is for, or alternatively you could so a sequence like:

While the condition remains untrue
Pause 5 seconds

Which is essentially what the Reduce CPU Usage option does, except you have no control on the pause length, and there are two values, one after 10 seconds, one after 60 seconds.

4 Likes

Oh cool that is very helpful. So I am guessing that it is even more than "while the condition remains untrue" because even that would have to keep checking if it was untrue if I understand right so "Reduce CPU Useage" just stops checking as often.

I love the explanation and thought behind how things are programmed in Keyboard Maestro. An amazing app to say the least. I spend hours in it everyday! What a blessing it is. So glad to have been forced to switch from QuicKeys.

1 Like