Josh Posted October 24, 2010 Share Posted October 24, 2010 I am getting this error when I use timeGetTime(): error C3861: 'timeGetTime': identifier not found I am including <windows.h> and using it to create a Win API window. I also included winmm.lib in the "Project Linker>Input>Additional Dependencies" setting. I searched my Visual Studio folder for winmm.lib but nothing was found. I might not have the PlatformSDK installed, so now I am looking for that...but the link to download it is dead, and the search on their site doesn't return any useful results!: http://www.microsoft.com/msdownload/platformsdk/sdkupdate/ Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Rick Posted October 24, 2010 Share Posted October 24, 2010 What VS version are you using? Are you using an Express version also? Quote Link to comment Share on other sites More sharing options...
Josh Posted October 24, 2010 Author Share Posted October 24, 2010 VS 2008 Express. I am having better results with the C clock() function. On my system, the resolution is 1000 ticks per second. The QueryPerformanceCounter() function I used earlier might be causing some time inaccuracies for some people's systems, according to the stuff I am reading. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Canardia Posted October 24, 2010 Share Posted October 24, 2010 Why do you use windows API functions, when there is also a cross-platform version available? You will only make the engine more bloated and buggy that way Use (double)clock()/(double)CLOCKS_PER_SEC for millisecond measurements, it's completely cross-platform, and it's always much more accurate than Windows API functions. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Pixel Perfect Posted October 24, 2010 Share Posted October 24, 2010 On my system the winmm.lib is in the Platform SDK folder. The latest download (iso image) that I could find is here: Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO) I have been using the QueryPerformanceCounter() function in my code for some years and have not experienced any issues but as you suggest there are certainly indications around that there can be problems on multi processor systems with this call. Quote Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++ Link to comment Share on other sites More sharing options...
Mumbles Posted October 24, 2010 Share Posted October 24, 2010 I am having better results with the C clock() function. On my system, the resolution is 1000 ticks per second. Well Josh, don't feel too bad, You already knew more than me. I never even knew clock() existed! All this time I've been using GetTickCount() you know, the one that only updates once every 16 ms on win32... Quote LE Version: 2.50 (Eventually) Link to comment Share on other sites More sharing options...
Roland Posted October 26, 2010 Share Posted October 26, 2010 Josh. You probably have this defined before the include of windows. I guess in stdafx.h #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include <windows.h> remove the WIN32_LEAN_AND_MEAN line and you will be fine //#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include <windows.h> Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Josh Posted October 26, 2010 Author Share Posted October 26, 2010 Roland is right. I read about the LEAN AND MEAN define statement, but thought it was something in your program source, and didn't know where else to look for it. Good to know. If clock() has milliseconds accuracy on all machines, I'll stick to that one. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Roland Posted October 26, 2010 Share Posted October 26, 2010 Roland is right. I read about the LEAN AND MEAN define statement, but thought it was something in your program source, and didn't know where else to look for it. Good to know. If clock() has milliseconds accuracy on all machines, I'll stick to that one. You have to be aware that using any of mentioned functions only gives you a best precision of 15 milliseconds. All those clock, timeGetTime, GetSystemTime etc... is updated on each NT clock interval, which is 15 milliseconds. You may read a more detailed description on how to get a bit better results in this article Implement a Continuously Updating, High-Resolution Time Provider for Windows Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Canardia Posted October 26, 2010 Share Posted October 26, 2010 That article is quite useless since it doesn't even mention the clock() command. On all machines I've tried, clock() the smallest millisecond accuracy on the machine. I made a test program which shows that Windows API calls use the same resolution as clock(). However clock() is more accurate since it starts with 0, so there will be no double/float precision errors when measuring the result: #include "stdio.h" #include "time.h" #include "windows.h" int main() { double t1,t2,tt; for(int z=0;z<10;z++) { t1=clock(); t2=clock(); // wait for smallest change (15ms on windows) while(t2<=t1)t2=clock(); tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/(double)CLOCKS_PER_SEC, t2/(double)CLOCKS_PER_SEC, tt/(double)CLOCKS_PER_SEC); } printf("-------------------------------------------------------\n"); for(int z=0;z<10;z++) { t1=GetTickCount(); t2=GetTickCount(); // wait for smallest change (15ms on windows) while(t2<=t1)t2=GetTickCount(); tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/1000.0, t2/1000.0, tt/1000.0); } return 0; } Output: 0.00000000 0.01500000 0.01500000 0.01500000 0.03100000 0.01600000 0.03100000 0.04600000 0.01500000 0.04600000 0.06200000 0.01600000 0.06200000 0.07800000 0.01600000 0.07800000 0.09300000 0.01500000 0.09300000 0.10900000 0.01600000 0.10900000 0.12500000 0.01600000 0.12500000 0.14000000 0.01500000 0.14000000 0.15600000 0.01600000 ------------------------------------------------------- 22676.37500000 22676.39000000 0.01500000 22676.39000000 22676.40600000 0.01600000 22676.40600000 22676.42100000 0.01500000 22676.42100000 22676.43700000 0.01600000 22676.43700000 22676.45300000 0.01600000 22676.45300000 22676.46800000 0.01500000 22676.46800000 22676.48400000 0.01600000 22676.48400000 22676.50000000 0.01600000 22676.50000000 22676.51500000 0.01500000 22676.51500000 22676.53100000 0.01600000 Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Roland Posted October 26, 2010 Share Posted October 26, 2010 That article is quite useless since it doesn't even mention the clock() command. On all machines I've tried, clock() the smallest millisecond accuracy on the machine. I made a test program which shows that Windows API calls use the same resolution as clock(). However clock() is more accurate since it starts with 0, so there will be no double/float precision errors when measuring the result: #include "stdio.h" #include "time.h" #include "windows.h" int main() { double t1,t2,tt; for(int z=0;z<10;z++) { t1=clock(); t2=clock(); // wait for smallest change (15ms on windows) while(t2<=t1)t2=clock(); tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/(double)CLOCKS_PER_SEC, t2/(double)CLOCKS_PER_SEC, tt/(double)CLOCKS_PER_SEC); } printf("-------------------------------------------------------\n"); for(int z=0;z<10;z++) { t1=GetTickCount(); t2=GetTickCount(); // wait for smallest change (15ms on windows) while(t2<=t1)t2=GetTickCount(); tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/1000.0, t2/1000.0, tt/1000.0); } return 0; } Output: 0.00000000 0.01500000 0.01500000 0.01500000 0.03100000 0.01600000 0.03100000 0.04600000 0.01500000 0.04600000 0.06200000 0.01600000 0.06200000 0.07800000 0.01600000 0.07800000 0.09300000 0.01500000 0.09300000 0.10900000 0.01600000 0.10900000 0.12500000 0.01600000 0.12500000 0.14000000 0.01500000 0.14000000 0.15600000 0.01600000 ------------------------------------------------------- 22676.37500000 22676.39000000 0.01500000 22676.39000000 22676.40600000 0.01600000 22676.40600000 22676.42100000 0.01500000 22676.42100000 22676.43700000 0.01600000 22676.43700000 22676.45300000 0.01600000 22676.45300000 22676.46800000 0.01500000 22676.46800000 22676.48400000 0.01600000 22676.48400000 22676.50000000 0.01600000 22676.50000000 22676.51500000 0.01500000 22676.51500000 22676.53100000 0.01600000 I don't know what new this brings to the subject. 15 msec is the resolution, as you also show in your example. About that article I have no further comments, its written by Johan Nilsson at Swedish Space Center. Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Canardia Posted October 26, 2010 Share Posted October 26, 2010 The new thing is that clock() starts with 0 when the program starts, and GetTickCount() starts from when the computer was started. So when you compare seconds as float or double, especially with float you will get accuracy problems very soon. Also new is that on Linux clock() has 10ms accuracy, while the Windows commands don't work at all on Linux, they don't exist in ANSI standard C++: 0.00000000 0.01000000 0.01000000 0.01000000 0.02000000 0.01000000 0.02000000 0.03000000 0.01000000 0.03000000 0.04000000 0.01000000 0.04000000 0.05000000 0.01000000 0.05000000 0.06000000 0.01000000 0.06000000 0.07000000 0.01000000 0.07000000 0.08000000 0.01000000 0.08000000 0.09000000 0.01000000 0.09000000 0.10000000 0.01000000 Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Roland Posted October 27, 2010 Share Posted October 27, 2010 The new thing is that clock() starts with 0 when the program starts, and GetTickCount() starts from when the computer was started. So when you compare seconds as float or double, especially with float you will get accuracy problems very soon. Also new is that on Linux clock() has 10ms accuracy, while the Windows commands don't work at all on Linux, they don't exist in ANSI standard C++: 0.00000000 0.01000000 0.01000000 0.01000000 0.02000000 0.01000000 0.02000000 0.03000000 0.01000000 0.03000000 0.04000000 0.01000000 0.04000000 0.05000000 0.01000000 0.05000000 0.06000000 0.01000000 0.06000000 0.07000000 0.01000000 0.07000000 0.08000000 0.01000000 0.08000000 0.09000000 0.01000000 0.09000000 0.10000000 0.01000000 Ok. I see. But still thats a small thing compared to the fact that you get time i 15 msec step using function thats may mislead you to believe that you have a real 1 msec timer. That's my point. About clock() and Linux I have no knowledge but if it is like you say that means that clock() different resolutions in Linux and Windows. That would make it a bad candidate then. Good research Lumooja. Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Mumbles Posted October 27, 2010 Share Posted October 27, 2010 There must be a way, surely. If I put a Sleep(1) in my code, surely windows is not using a hi-res timer for that? Quote LE Version: 2.50 (Eventually) Link to comment Share on other sites More sharing options...
Roland Posted October 27, 2010 Share Posted October 27, 2010 There must be a way, surely. If I put a Sleep(1) in my code, surely windows is not using a hi-res timer for that? Sleep(1) will give a sleep time between 0 and 15.6 milliseconds. If you test with a loop of Sleep(1) you will get results varying between those values, Precision is 15 milliseconds on Windows, no matter what method that i used. There are way to trim this to about 10 msec, but 1 msec... No. Then you can always start tinkering around with using multimedia timers that uses the hardware clock in the sound-card to make things better. But that does not always work either. So in the end. 15 msec precision is what you have. There may be some method to solve this that I don't know about. In that case I would be very pleased as this is a reoccurring problem in routines sending audio over internet which is something I work with right now. Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Josh Posted October 27, 2010 Author Share Posted October 27, 2010 That sounds bizarre because a 15 msec measurement is enormous in rendering time. But it wouldn't surprise me. How am I able to measure 1-2 msec time elapses? Wouldn't all my measurements be rounded off to the nearest 15 msecs? Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Canardia Posted October 27, 2010 Share Posted October 27, 2010 BlitzMax has 1ms accuracy, so there must be a better way still: SuperStrict Local t1:Double, t2:Double, tt:Double; For Local z:Int=0 To 9 t1=MilliSecs(); t2=MilliSecs(); While(t2<=t1) t2=MilliSecs(); Wend tt=t2-t1; Print t1/1000:Double+" "+t2/1000:Double+" "+tt/1000:Double; Next End Output: 5836.3750000000000 5836.3760000000002 0.0010000000000000000 5836.3760000000002 5836.3770000000004 0.0010000000000000000 5836.3770000000004 5836.3779999999997 0.0010000000000000000 5836.3779999999997 5836.3789999999999 0.0010000000000000000 5836.3789999999999 5836.3800000000001 0.0010000000000000000 5836.3800000000001 5836.3810000000003 0.0010000000000000000 5836.3810000000003 5836.3819999999996 0.0010000000000000000 5836.3819999999996 5836.3829999999998 0.0010000000000000000 5836.3829999999998 5836.3840000000000 0.0010000000000000000 5836.3840000000000 5836.3850000000002 0.0010000000000000000 Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Canardia Posted October 27, 2010 Share Posted October 27, 2010 I found some code on Microsoft site: http://msdn.microsoft.com/en-us/library/dd743626(v=VS.85).aspx http://msdn.microsoft.com/en-us/library/dd757629(VS.85).aspx Now you have 1ms accuracy in C++ too! Still need to test it on Linux. #include "stdio.h" #include "time.h" #include "windows.h" #pragma comment(lib,"winmm.lib") int main() { #define TARGET_RESOLUTION 1 // 1-millisecond target resolution TIMECAPS tc; UINT wTimerRes; if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { // Error; application can't continue. } wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION), tc.wPeriodMax); timeBeginPeriod(wTimerRes); // Actually the above is not needed, since the following command alone works also, // but maybe it's still better to use the above, who knows how Microsoft has // designed Windows: // // timeBeginPeriod(1); double t1,t2,tt; for(int z=0;z<10;z++) { t1=clock(); t2=clock(); while(t2<=t1)t2=clock(); // wait for smallest change (15ms on windows) tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/(double)CLOCKS_PER_SEC, t2/(double)CLOCKS_PER_SEC, tt/(double)CLOCKS_PER_SEC); } printf("-------------------------------------------------------\n"); for(int z=0;z<10;z++) { t1=GetTickCount(); t2=GetTickCount(); while(t2<=t1)t2=GetTickCount(); // wait for smallest change (15ms on windows) tt=(t2-t1); printf("%17.8f %17.8f %17.8f\n", t1/1000.0, t2/1000.0, tt/1000.0); } printf("-------------------------------------------------------\n"); for(int z=0;z<10;z++) { t1=timeGetTime(); t2=timeGetTime(); while(t2<=t1)t2=timeGetTime(); // wait for smallest change (1ms on windows) tt=t2-t1; printf("%17.8f %17.8f %17.8f\n", t1/1000.0, t2/1000.0, tt/1000.0); } return 0; } Output: 0.00000000 0.01500000 0.01500000 0.01500000 0.03100000 0.01600000 0.03100000 0.04600000 0.01500000 0.04600000 0.06200000 0.01600000 0.06200000 0.07800000 0.01600000 0.07800000 0.09300000 0.01500000 0.09300000 0.10900000 0.01600000 0.10900000 0.12500000 0.01600000 0.12500000 0.14000000 0.01500000 0.14000000 0.15600000 0.01600000 ------------------------------------------------------- 7210.39000000 7210.40600000 0.01600000 7210.40600000 7210.42100000 0.01500000 7210.42100000 7210.43700000 0.01600000 7210.43700000 7210.45300000 0.01600000 7210.45300000 7210.46800000 0.01500000 7210.46800000 7210.48400000 0.01600000 7210.48400000 7210.50000000 0.01600000 7210.50000000 7210.51500000 0.01500000 7210.51500000 7210.53100000 0.01600000 7210.53100000 7210.54600000 0.01500000 ------------------------------------------------------- 7210.53400000 7210.53500000 0.00100000 7210.53500000 7210.53600000 0.00100000 7210.53600000 7210.53700000 0.00100000 7210.53700000 7210.53800000 0.00100000 7210.53800000 7210.53900000 0.00100000 7210.53900000 7210.54000000 0.00100000 7210.54000000 7210.54100000 0.00100000 7210.54100000 7210.54200000 0.00100000 7210.54200000 7210.54300000 0.00100000 7210.54300000 7210.54400000 0.00100000 Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Mumbles Posted October 27, 2010 Share Posted October 27, 2010 timeGetTime() ... which is exactly what Josh was trying to use in the first place. Quote LE Version: 2.50 (Eventually) Link to comment Share on other sites More sharing options...
Canardia Posted October 27, 2010 Share Posted October 27, 2010 Yeah, but by default timeGetTime() is set to 15ms accuracy, so you need to change the timer accuracy to 1ms using timeBeginPeriod(1) (or better the complex formula using devicecaps, to make sure 1 is allowed). There also another funny thing: when you change the accuracy with timeBeginPeriod() to 1ms, it doesn't change until after 2ms delay, but that should not be a real problem, since it can be done when the engine starts. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Canardia Posted October 27, 2010 Share Posted October 27, 2010 I found an article how to do it on Linux too: http://stackoverflow.com/questions/588307/c-obtaining-milliseconds-time-on-linux-clock-doesnt-seem-to-work-properly Now you have 1ms accuracy on Windows and Linux! #include <sys/time.h> #include <stdio.h> long timeGetTime(); long system_starttime=timeGetTime(); long timeGetTime() { struct timeval start; long mtime; gettimeofday(&start, NULL); mtime = (1000*start.tv_sec + start.tv_usec/1000.0) + 0.5 - system_starttime; return mtime; } int main() { double t1,t2,tt; for(int z=0;z<10;z++) { t1=timeGetTime(); t2=timeGetTime(); while(t2<=t1)t2=timeGetTime(); tt=t2-t1; printf("%17.8f %17.8f %17.8f\n", t1/1000.0, t2/1000.0, tt/1000.0); } return 0; } Output: 0.00000000 0.00100000 0.00100000 0.00100000 0.00200000 0.00100000 0.00200000 0.00300000 0.00100000 0.00300000 0.00400000 0.00100000 0.00400000 0.00500000 0.00100000 0.00500000 0.00600000 0.00100000 0.00600000 0.00700000 0.00100000 0.00700000 0.00800000 0.00100000 0.00800000 0.00900000 0.00100000 0.00900000 0.01000000 0.00100000 Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Canardia Posted October 27, 2010 Share Posted October 27, 2010 Oh cool, the same Linux article says in the end, it works the same way on Mac too. So now you have 1ms accuracy on Windows, Linux, Mac! Basically since all phones are Linux (only iPhone is Mac), you can use the same code for all phones too. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Mumbles Posted October 28, 2010 Share Posted October 28, 2010 I tried your C++ code with a Sleep(1) just after the printing. The result is increments of two milliseconds. still not the 16 everything else gets. So, when I thought: There must be a way, surely. If I put a Sleep(1) in my code, surely windows is not using a hi-res timer for that? Sure enough, it really was only sleeping for 1 ms. Just a shame you have to jump through so many hoops to count 1 ms yourself. Still, I guess we should all be thanking Josh. If he hadn't asked this question, would this discovery have been posted? And of course obviously to Lumooja as well, for actually finding this out... Quote LE Version: 2.50 (Eventually) Link to comment Share on other sites More sharing options...
Canardia Posted October 28, 2010 Share Posted October 28, 2010 With the new timing, you can make your own accurate Sleep() function, which really sleeps for 1ms, and not 2. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Roland Posted October 28, 2010 Share Posted October 28, 2010 With the new timing, you can make your own accurate Sleep() function, which really sleeps for 1ms, and not 2. Yes. Thanks Lumooja for this effort. Will be very handy. Quote Roland Strålberg Website: https://rstralberg.com Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.