Wait Until CPU Usage Less to Process AHK Script

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 18 Jul 2023, 19:13

I've noticed that some of the scripts I use everyday don't work properly when my CPU usage is high. For example, I have scripts which add a new row to a Word document and insert information in my Word table which type everything in the wrong spot when my antivirus program is updating or my Windows OneDrive is syncing.

Is there anyway to add something like the following in my AHK scripts:

Code: Select all

loop {
If CPU usage < 50%
 Then run rest of script
Else if CPU usage > 50%
  msgbox, CPU usage is too high ... will try again later
  Sleep, 10000
   Then run rest of script
}
Or maybe I should just pause OneDrive and my antivirus while running my AHK script?

?

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 18 Jul 2023, 20:15

Code: Select all

; This script waits for CPU load to drop before proceeding
#Requires AutoHotkey v1.1.33
SoundBeep 1500
SetTimer go, -1
SoundBeep 1000
waitCPU(15)
ToolTip
MsgBox 64, Status, Done!, 1

go() {
 Loop 100 {
  Sleep 1
  ToolTip % "===> " A_Index " <==="
 }
}

CPULoad() { ; CPULoad() by SKAN
 ; https://github.com/jNizM/SysMeter/blob/master/src/SysMeter.ahk#L335
 Static PIT, PKT, PUT
 If (PIT = "")
  Return 0, DllCall("GetSystemTimes", "Int64P", PIT, "Int64P", PKT, "Int64P", PUT)
 DllCall("GetSystemTimes", "Int64P", CIT, "Int64P", CKT, "Int64P", CUT)
 IdleTime := PIT - CIT, KernelTime := PKT - CKT, UserTime := PUT - CUT
 SystemTime := KernelTime + UserTime
 Return (SystemTime - IdleTime) * 100 // SystemTime, PIT := CIT, PKT := CKT, PUT := CUT
}

cpu() {
 n := 0, load := []
 While (n < 4) {
  If (0 < c := CPULoad())
   load[n := Mod(n, 4) + 1] := c
  Sleep, 100
 }
 Return Round((load.1 + load.2 + load.3 + load.4) / 4)
}

waitCPU(pct) {
 While cpu() > pct
  Sleep, 500
}

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 18 Jul 2023, 23:17

Thank you, Mikeyww!!!

If I correctly understand the SysMeter script, I could also use the following function to wait until RAM fell below a certain percent:

Code: Select all

GlobalMemoryStatusEx()
{
	MEMORYSTATUSEX := Buffer(64, 0)
	NumPut("uint", 64, MEMORYSTATUSEX)
	if (DllCall("kernel32\GlobalMemoryStatusEx", "ptr", MEMORYSTATUSEX))
		return NumGet(MEMORYSTATUSEX, 4, "uint")
		;return Round(100 - NumGet(MEMORYSTATUSEX, 16, "uint64") / NumGet(MEMORYSTATUSEX, 8, "uint64") * 100, 2)
	return false
}
?

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 19 Jul 2023, 05:15

A high CPU load might interfere with what running programs are doing. A high memory load might interfere with very little, depending on the programs. I find that Windows tends to be good at managing memory.

You could have one small program consuming the CPU, or 100 large programs doing almost nothing. Different question, different script.

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 10:23

Understood. Thank you.

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 14:33

mikeyww wrote:
18 Jul 2023, 20:15

Code: Select all

; This script waits for CPU load to drop before proceeding
#Requires AutoHotkey v1.1.33
SoundBeep 1500
SetTimer go, -1
SoundBeep 1000
waitCPU(15)
ToolTip
MsgBox 64, Status, Done!, 1

go() {
 Loop 100 {
  Sleep 1
  ToolTip % "===> " A_Index " <==="
 }
}

CPULoad() { ; CPULoad() by SKAN
 ; https://github.com/jNizM/SysMeter/blob/master/src/SysMeter.ahk#L335
 Static PIT, PKT, PUT
 If (PIT = "")
  Return 0, DllCall("GetSystemTimes", "Int64P", PIT, "Int64P", PKT, "Int64P", PUT)
 DllCall("GetSystemTimes", "Int64P", CIT, "Int64P", CKT, "Int64P", CUT)
 IdleTime := PIT - CIT, KernelTime := PKT - CKT, UserTime := PUT - CUT
 SystemTime := KernelTime + UserTime
 Return (SystemTime - IdleTime) * 100 // SystemTime, PIT := CIT, PKT := CKT, PUT := CUT
}

cpu() {
 n := 0, load := []
 While (n < 4) {
  If (0 < c := CPULoad())
   load[n := Mod(n, 4) + 1] := c
  Sleep, 100
 }
 Return Round((load.1 + load.2 + load.3 + load.4) / 4)
}

waitCPU(pct) {
 While cpu() > pct
  Sleep, 500
}
Mikeyww, now that I've had a chance to play around with your script, I have a quick question ...

Does the script work by:

(1) Setting a threshhold maximum for cpu load to escape the loop? If so, how can I change that thresshold number?

Or

(2) By counting from 1 to 100, and if there is enough cpu to finish counting to 100, then it escapes the loop?

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 19 Jul 2023, 14:36

Line 6 means, wait until load falls to 15% or less.

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 15:48

Thank you!!!

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 16:58

Mikeyww, if my computer has more than one processor core (I have 4), do I need to modify the script? I see that some people added the following line in scripts involving cpu measurement:

Code: Select all

EnvGet, ProcessorCount, NUMBER_OF_PROCESSORS
Or is this section of your script looking at 4 cores:

Code: Select all

cpu() {
 n := 0, load := []
 While (n < 4) {
  If (0 < c := CPULoad())
   load[n := Mod(n, 4) + 1] := c
  Sleep, 100
 }
 Return Round((load.1 + load.2 + load.3 + load.4) / 4)
?

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 19 Jul 2023, 20:32

I don't think you need to change it, but you could check with SKAN. You can also validate the output against what the Windows Task Manager shows. The last time I examined that, the numbers were close to each other. In the past, I did find some other scripts that did not actually work (accurately). You can see, too, that this script uses a running average of the last four positive values. It seems to help.

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 20:38

Thanks! It does seem like your script is super helpful. I'll play around with it.

AlFlo
Posts: 363
Joined: 29 Nov 2021, 21:46

Re: Wait Until CPU Usage Less to Process AHK Script

Post by AlFlo » 19 Jul 2023, 22:46

mikeyww wrote:
19 Jul 2023, 20:32
I don't think you need to change it, but you could check with SKAN. You can also validate the output against what the Windows Task Manager shows. The last time I examined that, the numbers were close to each other. In the past, I did find some other scripts that did not actually work (accurately). You can see, too, that this script uses a running average of the last four positive values. It seems to help.
SKAN confirmed that his CPULoad() script can measure the CPU of multiple cores.

hiahkforum
Posts: 47
Joined: 08 Feb 2024, 04:21

Re: Wait Until CPU Usage Less to Process AHK Script

Post by hiahkforum » 31 Mar 2024, 02:11

Hi @mikeyww, could you please help me to adapt your script for v2? I took CPULoad() for v2 from here: https://github.com/jNizM/SysMeter/blob/master/src/SysMeter_Simple.ahk#L108; and tried to change syntax a bit, but got an error:
Error: Invalid index.

Specifically: 1

029: {
030: If (0 < c := CPULoad())
▶ 031: load[n := Mod(n, 4) + 1] := c
032: Sleep(100)
033: }

Code: Select all

#Requires AutoHotkey v2.0
SoundBeep 1500
SetTimer go, -1
SoundBeep 1000
waitCPU(15)
ToolTip
MsgBox 'Done!', 'Status', 'Iconi T1'

go() {
 Loop 100 {
  Sleep 1
  ToolTip "===> " A_Index " <==="
 }
}

CPULoad() { ; CPULoad() by SKAN
; https://github.com/jNizM/SysMeter/blob/master/src/SysMeter_Simple.ahk#L108
	Static PIT := 0, PKT := 0, PUT := 0

	DllCall("kernel32\GetSystemTimes", "int64*", &CIT := 0, "int64*", &CKT := 0, "int64*", &CUT := 0)
	IdleTime := PIT - CIT, KernelTime := PKT - CKT, UserTime := PUT - CUT
	SystemTime := KernelTime + UserTime

	PIT := CIT, PKT := CKT, PUT := CUT
	return ((SystemTime - IdleTime) * 100) // SystemTime
}

cpu() {
 n := 0, load := Array()
 While (n < 4) {
  If (0 < c := CPULoad())
   load[n := Mod(n, 4) + 1] := c
  Sleep 100
 }
 Return Round((load.1 + load.2 + load.3 + load.4) / 4)
}

waitCPU(pct) {
 While cpu() > pct
  Sleep 500
}

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 31 Mar 2024, 05:54

Attempting to use an array index which is out of bounds (such as zero, or if its absolute value is greater than the Length of the array) is considered an error and will cause an IndexError to be thrown. The best way to add new elements to the array is to call InsertAt or Push.
Source: Array Object - Methods & Properties | AutoHotkey v2

Code: Select all

cpu() {
 load := []
 While load.Length < 4 {
  (0 < c := CPULoad()) && load.Push(c)
  Sleep 100
 }
 Return Round((load[1] + load[2] + load[3] + load[4]) / 4)
}

Code: Select all

cpu() {  ; Get the mean CPU time
 ; CPU time    = percentage of available CPU time that the processor spent executing code.
 ; CPU utility = percentage of total computational capacity actually used at the current CPU frequency.
 ; In Windows Task Manager, "Details" view shows CPU time, but "Processes" view shows CPU utility.
 Static n2   := 5   ; Number of values to average
      , wait := 100 ; Delay between checks
 n1 := sum := 0
 While n1 < n2 {
  Sleep wait * (A_Index > 1)
  If c := CPULoad()
   sum += c, n1++
 }
 Return Round(sum / n2)
}

hiahkforum
Posts: 47
Joined: 08 Feb 2024, 04:21

Re: Wait Until CPU Usage Less to Process AHK Script

Post by hiahkforum » 09 Apr 2024, 08:34

Thank you! But it’s strange that to express gratitude it is obligatory to reply and raise the topic to the top; there is clearly a lack of a reputation system or a simple “thank you!” button. Therefore, I express my gratitude only now...

@mikeyww, I tried to embed your function in my script, and it turned out to be not so obvious. Everything works fine with the go() function, but I tried, following your example, to wrap another simple function in SetTimer(), but it doesn’t work. I'm guessing here again the reason is "AHK is single threaded!", so the only option is to keep the second script with your function open?

Code: Select all

SoundBeep 1500
SetTimer NotepadEnum, -1
SoundBeep 1000
waitCPU(15)

NotepadEnum() {
  SetKeyDelay(10, 10)
  Loop WinGetCount('ahk_class Notepad') {
    SendEvent('#t{End}{Enter}{Tab ' A_Index-1 '}{Enter}')
    WinSetTitle(A_Index '. ' RegExReplace(WinGetTitle('A'), '[0-9]\.\s'), 'A')
  }
}

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 09 Apr 2024, 10:15

Without knowing what effect you hope to achieve, I cannot comment on a way to achieve it. "It doesn’t work" says nothing about what the script does, or what it should do.

hiahkforum
Posts: 47
Joined: 08 Feb 2024, 04:21

Re: Wait Until CPU Usage Less to Process AHK Script

Post by hiahkforum » 10 Apr 2024, 01:54

I have reduced my function as much as possible, leaving only the most basic functionality, so that it does not cause difficulties for understanding, but apparently it needs to be further described in words. Overall, this is just an example and I couldn't get it to work with anything else I tried. I feel like I'm somehow using this incorrectly.

In this version, the function moves the focus to the last position on the taskbar, where the icon with open notepad windows should be located in advance, activates them in the order that is on the taskbar and gives them a serial number. I expected that if, for example, the CPU load is above 15%, then your function should pause the execution of my function, but this does not happen. Despite SetTimer(), my function is executed first, and only then yours checks the processor load and waits for the load to decrease, and then closes the script.

User avatar
mikeyww
Posts: 27366
Joined: 09 Sep 2014, 18:38

Re: Wait Until CPU Usage Less to Process AHK Script

Post by mikeyww » 10 Apr 2024, 06:33

To wait with each iteration, you can move the waitCPU function call into your function.

Post Reply

Return to “Ask for Help (v1)”