mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
The frequency that a multimedia timer gets called - has an impact on the ability to have good performance in mIRC-scripted games.

This script shows the number of times a -h timer can be called per second. It is wildly fluctuating from one mIRC session to another, regardless of the same version, and regardless whether /remote is on|off. I've run this alias in versions from 7.55 through 7.62, and the results within each version fluctuates all the way from 65-per-second to 240-per-second. After running /testtimer, I can "/exit -nr" to restart the client then run the alias again, and the result can sometimes be 65, 115, 160, 200, 240.

Once the results begin showing after a restart, they seem to stay that way as long as the session continues, but the prior results seem to have no bearing on what the results will be after a restart. I even see this with "/remote off" and without connecting to any IRC networks.

For better game-play with some mIRC games, the user would need to keep restarting and running this alias, until the client finally starts up with a higher number, as this is an estimate of how many times a multimedia timer could be called within a 1 seconds interval. The last time I did something similar to this with a game was to change to the same network server as a trivia bot used, so the lag time was shorter.

Note that this timer runs forever until you do: /timertest off

Code
alias testtimer {
  inc %testtimer
  if ($calc($ticks - %testtimerticks) >= 1000) {
    inc %testtimer.count
    inc %testtimer.tot.secs %testtimer
    echo -s total inc per second: %testtimer avg: $calc(%testtimer.tot.secs / %testtimer.count)
    unset %testtimer
    if (!$ctimer) unset %testtimer.count %testtimer.tot.secs
    set %testtimerticks $ticks
  }
  .timertest -ho 1 0 testtimer
}

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Thanks for your bug report. This has been brought up several times over the years and I have explained it in previous posts. There are so many variables that can affect /timers, from memory allocation and fragmentation, interactions with other timers and timer-based features, Windows thread scheduling/core switching, Windows message processing, tick count precision, and so on. The multimedia timer is as good as it gets for millisecond triggers (although note that Windows has actually deprecated multimedia timers and replaced them with timer queues, which are less accurate). However, that does not mean that mIRC will trigger on every high resolution timer event - that is impossible. There is so much going on that these will necessarily be delayed so that mIRC can manage other features. If you are creating games that depend on short millisecond triggers, you will need to rethink your game design to work within the context of these limitations and, of course, of an IRC client, which is mIRC's primary purpose.

Joined: Jan 2004
Posts: 2,127
maroon Offline OP
Hoopy frood
OP Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
A small correction for the above alias, and a question.

For the above alias to work after a reboot when $ticks is reset to a much lower number, the ">= 1000" should be changed to "!isnum 0-1000".

I do see that if I create another alias where all the 'test' strings were changed to 'test3', and if I run 2-or-more of these cloned aliases at the same time, the average times are lowered so that the sum of these averages are slightly higher, in a way which indicates that, other than at the 16ms system ticks interval, the other multimedia trigger events are only triggering 1 multimedia timer at each event.

When I edit the alias to use -mo instead of -ho switch, the result changes to 65 which is the number of 16ms system-timer intervals per second.

So, when the multimedia -ho timer in this alias has result of 65 when run as the only timer, does that mean the multimedia settings are silently disabled, and in-effect the timer is behaving in all ways as a non-multimedia -m timer even though $timer(test).mmt returns $true?

Currently, when $timer(foo).delay reports 5000, there's no way for a script to know if that delay is 5000 seconds or 5000ms unless the timer was created with the -h switch, allowing $timer(foo).mmt to indicate the delay is shown in .ms. But if -h wasn't used, .delay can't inform whether or not the timer was created with -m. Even if you do know the timer is a -m or -h timer where the .delay is in millisecs, a script can't use .secs to know how many milliseconds remain until the next scheduled triggering, because .secs returns the rounded-down seconds, so 0 just means there's somewhere between 0-999 ms remaining.

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
Quote
So, when the multimedia -ho timer in this alias has result of 65 when run as the only timer, does that mean the multimedia settings are silently disabled, and in-effect the timer is behaving in all ways as a non-multimedia -m timer even though $timer(test).mmt returns $true?

It is still a multimedia timer :-)

As the results are consistent during an application run, it looks like the application is being assigned to either a particular core, thread processing order, etc. that determines when the multimedia timer interrupt updates the tick count relative to when the timer is triggered, and this affects the time elapsed measurement. In other words, the tick count update vs the timer trigger may be in or out of sync, determined at the time the application is run. It could even be due to high resolution vs non-high resolution tick count measurements, since the high resolution tick count measurement can only take place after a multimedia timer is started.

Timers are tricky. mIRC's timer source code includes commented out test code for five different methods of triggering timers and five different methods of retrieving a tick count. The actual timer code uses four different methods of measuring tick count, depending on whether certain APIs are supported on your version of Windows and/or whether a multimedia timer is being used. In addition, the multimedia timer is set to trigger no lower than every 5ms, even if a scripter requests a 1ms timer, due to the impact multimedia timers have on system resources.

Couple the above with Windows messages being used to relay timer events, along with the other issues mentioned in my previous post, and there are quite a few possible causes for what you are seeing.

I will add this to my to-do list to look into in the next beta cycle.

Joined: Dec 2002
Posts: 5,411
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 5,411
After comparing tick count results from different APIs, it looks like the issue is due to two factors.

First, when an application is started, it is assigned to a core, or some other interrupt-related state, that determines the order in which different tick count APIs (GetTickCount(), GetTickCount64(), QueryPerfomanceCounter(), timeGetTime(), GetSystemTimePreciseAsFileTime(), etc.) update their results. This is similar to what is being reported here.

Second, different tick count APIs return results that are close but not identical, and may, in the same run, lag behind or be ahead of other methods, even if they are of higher resolution. The standard deviation will depend on the above.

mIRC uses different methods of determining tick count, based on Windows version, which APIs are available, and whether the multimedia timer is being used.

The issue you are seeing seems to be due to /timer using different tick count measures at different points to calculate elpased timed. Due to the variable lag mentioned above, this leads to a bias in elapsed time measurement per application run.

I have changed how /timer -h uses tick counts and tested it on Windows XP, 7, and 10 and this seems to have resolved the issue. This change will be in the next beta.


Link Copied to Clipboard