etcimon / libasync

Cross-platform event loop library of asynchronous objects
MIT License
147 stars 30 forks source link

Timer performance #53

Closed vl-01 closed 8 years ago

vl-01 commented 8 years ago

When I make an AsyncTimer with a periodic duration of 30.msecs, it runs 14 times a second. If I put this to 2.msecs or so, it runs up to 24 times a second. To sketch an example:

int x; auto t = new AsyncTimer.periodic.duration(30.msecs); t.run((){ x++; }); for(...) getThreadEventLoop.loop;

After 1 second, x is 14. After 2, its usually about 26. If I set a 0.msecs timeout on the loop and increment another integer in the for(...) body, I find that the loop actually runs 450k+ times in 2 seconds. So there is not an inherent performance reason that the callback shouldn't be firing around 60 times in that 2 second period. If I decrease the period to 16.msecs, I find that x is 37 after 2 seconds.

Am I using it wrong? Why is the actual firing rate less than half what I am asking for?

I am on Windows 10, quadcore 2.16GHz. Using dmd, this happens regardless of whether I am building debug or release.

etcimon commented 8 years ago

To prevent the timer from firing too soon, it is majored by 30 msecs.

https://github.com/etcimon/libasync/blob/master/source/libasync/windows.d#L335

This was the only way to fix an issue I had been having in a webserver. I could move this to a higher level perhaps.

vl-01 commented 8 years ago

That would be useful. Perhaps if there is some D equivalent of passing a define as a compiler flag, the rate limiting could be set that way?

Anyway I have set the duration padding to 0 and a 50Hz loop still fires about 32 times per second. It seems to be moving faster but still not close to the requested rate.

etcimon commented 8 years ago

I decided to remove the 30msec delay because my apps now run fine without it, this was probably a false fix from an issue that was caused by something else a year back.

etcimon commented 8 years ago

Anyway I have set the duration padding to 0 and a 50Hz loop still fires about 32 times per second. It seems to be moving faster but still not close to the requested rate.

Sorry, I missed that part. This could be explained by the fact that the timer resolution is ~15ms in windows 10 https://vvvv.org/contribution/windows-system-timer-tool

So if you launch it every 20ms, it could add up to 20+15=35ms, which results in firing ~29 times

vl-01 commented 8 years ago

I was afraid it was something like that. I wonder how games function so well in Windows if the timer resolution is so poor?

etcimon commented 8 years ago

I found this article about it: https://www.reddit.com/r/Windows10/comments/3oatuw/those_of_you_gaming_on_windows_10_heres_how_i/

vl-01 commented 8 years ago

Interesting. Thanks! It looks like there are some windows API calls to change the timer resolution: https://msdn.microsoft.com/en-us/library/windows/desktop/dd743626(v=vs.85).aspx

etcimon commented 8 years ago

Awesome, what was your minimum set to? Feel free to add that as a parameter if it works