High Resolution Timer

Ask gaming related questions (AHK v1.1 and older)
dcraig327
Posts: 4
Joined: 03 Jul 2022, 21:22

High Resolution Timer

Post by dcraig327 » 03 Jul 2022, 23:02

Hi. First post. Been using AHK for a while. (I wish it'd get bundled into Windows already. 8-) )

A High Resolution Timer in AHK? What and why?

I'm currently playing Dwarf Fortress and seeking a fix to this bug in one of the mods (TWBT). The solution is pretty straight-forward, I'll explain the why first. There's several menu's in game and ESC closes those menus, like a normal game where you press ESC to open a menu, then ESC to close it. Here, there's several hotkeys you press to open different menus, each menu covers up the entire game window, and ESC closes them to get you back to the game. After you press ESC though, the game renders a grey screen, then it renders the game windows. The game window has your map on the left and your hotkeys on the right. However the bug will render the map view as a black screen right after closing any menu in-game. F12 redraws the map.

When I press ESC, I need to wait some time, then send F12 to the game.

Code: Select all

#Persistent
#MaxThreadsBuffer On

wintitle := "Dwarf Fortress.exe"
#If WinActive("ahk_exe" wintitle)
Esc::
  Send {Esc}
  Loop, 8 {
    redraw(5)
  }
Return

redraw(time)
{
  Sleep, time
  Send {F12}
}

Loop 8 times? 5ms? #MaxThreadsBuffer On?

That "wait some time" changes depending on which menu I opened in game. I've recorded some footage using OBS and stepped through the footage frame-by-frame to determine what's the min and max amount of time needed before the grey screen becomes the game screen (but with a black map). It ranges from 10-22 frames @ 60fps. Anything under 20ms (12/60 fps) isn't noticeable by an average human. So I should set the first call to redraw() to 20ms right? In my testing, no. There's some delay before the AHK code gets executed, then there's some delay before the game recognizes the {F12}.

#MaxThreadsBuffer On - This lets you run the same hotkey multiple times, so I could press ESC twice and it'll execute them both. Which is needed solely due to the ESC key opening a menu and in that menu you press ESC again to close it. Closing that takes 10 frames. Fastest of any of them.

The 8 loops is to make sure i hit all possible delays. Plus I'm testing this with a new save, as it progresses, the game slows down a lot.
I tried variable delays to time them to what's needed per the testing, even tried starting with 1x 20ms sleep, then a 20x loop of 1ms sleeps. That didn't work so well, likely due to the overhead and the ... massive issue with Windows.

Windows can only give you a timer resolution of that is 2.2ms or higher.


I stumbled upon this post in the archives, and this post is the reason I'm here: https://www.autohotkey.com/board/topic/18446-high-resolution-timer-ii/


Just as the OP did in the post, I was, :headwall: years ago, and not understanding it as nothing made sense. So I tested a lot. Per my testing using some C++ code in Windows vs Linux last year. I asked, what is the longest interval between notifications to my timer. I got averages by doing so:

[*]OS: avg - max
[*]Win10: 1.1ms - 2.2ms
[*]Linux: 27ns - 70us

Here's a legend: 1000ms = 1sec. 1000us = 1ms. 1000ns = 1us. A 4GHz CPU = 0.25ns per Hz (1 / 4,000,000,000 seconds/Hz)

The brilliant code used here: https://gist.github.com/sayurin/f47ddf0db901c1e0c5a905c718a749d1

In that code the various Win api functions to call are measured. In the Linux test. The standard deviation was not only much lower, but it was consistent. I tried it in Linux millions of times and it always came to 27ns, each time I ran it over 1000 times there was one that hit something high (70us). Point is That link shows how unpredictable Windows Kernel is and my conclusion, don't rely on Windows to give you a timer more accurate than 2.2ms, and I'd probably round it up to 3ms.

If sub-3ms is something you need, don't use Windows, or use specialized hardware/software which bypass the timers provided by the windows kernel to achieve it. I don't remember Windows ever hitting a 1ms timer guaranteed. In old Windows versions, there was SoftICE and we could find out why this is the case and try to fix it, but not any more. Why is the max in that test important? Think about it. If you wanted to get a 2ms timer. You tested it thousands of times and the highest delay was 2.2ms, then you can't reliably expect a timer under 2.2ms. I mentioned other OS/Hardware. Think about a pacemaker. If I had a pacemaker, I'd never have it run on Windows or Linux. There's Real-time operating systems for Embedded software that guarantee, when you need it at a precise time, you get it.

This is where I am. Looking at that AHK code above. Knowing, there's so many hidden variables and no promises or direction provided by Microsoft. I came to these forums searching for a way to make the code just a bit more efficient and todo that I'd have to have an accurate way to get the time. I'm not sure howto using AHK & WIndows. I'm not even sure if calling Sleep(1) a bunch of times will work as I expect it. I settled for a 8x5ms loop that I'll slowly reduce as I use it more.

I was curious how to get an accurate timer in AHK.
I doubt it's possible in Windows.
Last edited by gregster on 03 Jul 2022, 23:08, edited 1 time in total.
Reason: Topic moved from 'Scripts and Functions'.

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

Re: High Resolution Timer

Post by mikeyww » 05 Jul 2022, 05:29

Not my area, but have a look at :arrow: Sleep. In some cases, you can also use a Loop that checks A_TickCount.

Post Reply

Return to “Gaming Help (v1)”