[gelöst] Zeitauflösung von Sleep und co. erhöhen?
-
Hallo liebe Community,
mein Problem ist die Auflösung der Zeit beim suspenden vom Threads (sleep).
Diese würde ich gerne erhöhen.
(Ich programmiere mit VC++ Express 2005 unter WinXP SP3.)Nun zu den Details:
mit dem normalen
void WINAPI GetSystemTimeAsFileTime( __out LPFILETIME lpSystemTimeAsFileTime );
bekommt man die Zeit ja bekanntlich mit einer Auflösung von ca 12-16ms.
(Wenn ich eine Messung mache, kommen bei mir ca. 15,6ms heraus.)Da ich bei einer Anwendung eine höhere Präzision benötige, benutze ich
BOOL WINAPI QueryPerformanceFrequency( __out LARGE_INTEGER *lpFrequency );
und
BOOL WINAPI QueryPerformanceCounter( __out LARGE_INTEGER *lpPerformanceCount );
.
Das funktioniert auch sehr gut.Wenn ich allerdings einen Thread für ein paar Millisekunden suspenden will, möchte ich natürlich keine selbstgeschriebene "busy wait"-Funktion benutzen, die die CPU-Last auf 100% jagt, sondern würde das gerne weiterhin vom Kernel interruptgesteuert managen lassen.
VOID WINAPI Sleep( __in DWORD dwMilliseconds );
hat ja allerdings die niedrige Zeitauflösung.
Gibt es ein hochauflösendes Pendant dazu?Ich habe auch schon versucht, die Auflösung zu erhöhen
#include <windows.h> #include <iostream> using namespace std; int main( int argc, char* argv[] ) { typedef long ( __stdcall *NtQueryTimerResolutionFuncPtr ) ( unsigned long*, unsigned long*, unsigned long* ); typedef long ( __stdcall *NtSetTimerResolutionFuncPtr ) ( unsigned long, bool, unsigned long* ); HINSTANCE hntdll = LoadLibrary( "ntdll.dll" ); if( hntdll == NULL ) return 1; NtSetTimerResolutionFuncPtr NtSetTimerResolution = reinterpret_cast <NtSetTimerResolutionFuncPtr> ( GetProcAddress( hntdll, "NtSetTimerResolution" ) ); NtQueryTimerResolutionFuncPtr NtQueryTimerResolution = reinterpret_cast <NtQueryTimerResolutionFuncPtr> ( GetProcAddress( hntdll, "NtQueryTimerResolution" ) ); if ( ( NtQueryTimerResolution == NULL ) || ( NtSetTimerResolution == NULL ) ) return 2; unsigned long minimumResolution( 0 ); unsigned long maximumResolution( 0 ); unsigned long currentResolution( 0 ); NtQueryTimerResolution( &minimumResolution, &maximumResolution, ¤tResolution ); cout << "minimumResolution: " << minimumResolution << "; maximumResolution: " << maximumResolution << "; currentResolution: " << currentResolution << endl; unsigned long desiredResolution( ( minimumResolution + maximumResolution ) / 2 ); bool setResolution( true ); currentResolution = 0; long NtSetTimerResolutionStatus( NtSetTimerResolution( desiredResolution, setResolution, ¤tResolution ) ); cout << "desiredResolution: " << desiredResolution << "; setResolution: " << setResolution << "; currentResolution: " << currentResolution << endl; cout << "NtSetTimerResolutionStatus: " << NtSetTimerResolutionStatus << endl; return 0; }
hatte damit aber wie man am der Ausgabe sieht
minimumResolution: 156250; maximumResolution: 10000; currentResolution: 9766 desiredResolution: 83125; setResolution: 1; currentResolution: 9766 NtSetTimerResolutionStatus: 0
auch kein Glück.
Also, es wäre super, wenn mir jemand dabei helfen könnte, entweder ein hochauflösendes Sleep zu finden oder die Zeitauflösung generell zu erhöhen.
Vielen Dank im Voraus
Dobi
-
Du kannst die meisten Funktionen auf 1-2ms runterbringen, mit timeBeginPeriod().
Besser als das geht soweit ich weiss nicht.
-
*ABO*
-
zeusosc schrieb:
*ABO*
Hmm? Abonnement? Abort?
Hilf mir mal bitte auf die Sprünge was Du damit meinst...Martin
-
achso,..
das habe noch von mikrocontroller.net,...D.h. ich will per mail die info erhalten das jemmand sein senf zu diesem thread gegeben hat ohne das ich eigentlich mich daran beteilige...
Quasi ein abo
-
@zeusosc: http://i48.tinypic.com/ostz80.png
@hustbaer: Ich hab' mal
timeBeginPeriod( 1 ); ZeitAusgabeTest(); timeEndPeriod( 1 );
gesagt, aber meine Zeitauflösung hat sich dadurch leider auch nicht verbessert.
12:58:59.031 12:58:59.046 12:58:59.062 12:58:59.078 12:58:59.093 12:58:59.109 12:58:59.125 12:58:59.140 12:58:59.156 12:58:59.171 12:58:59.187 12:58:59.203 12:58:59.218 12:58:59.234 12:58:59.250 12:58:59.265 12:58:59.281
Muss ich dabei noch irgendetwas anderes beachten?
Die Zeit frage ich mit GetSystemTimeAsFileTime ab.
-
hmm,.... dann mache ich das nächste mal so
thx
-
Hallo Dobi,
wie siet denn
ZeitAusgabeTest
aus ?
Danke, Gruß Frank
-
Hi
Denke dass bei dir die Funktion ZeitAusgabeTest(); zu viele Cpu cycles braucht! Daher die schlechte Performance.
Lowbyte
-
Warum brauchst du eine so geringe Auflösung?
-
Hallo zusammen,
die 16 ms zwischen den Logmeldungen kommen deshalb zustande,
weil es meiner erfahrung nach unter windows (XP) nicht möglich ist sich in kleineren Zeitintervallen (auf nichts) zu suspendieren.So sorgt z.B. ein Sleep (1) immer für eine Wartezeit von ca. 16 [ms].
Möchte man kleinere Zeitabstände ohne CPU Last warten,
so ist daß meines Wissens nach nur IRQ getrieben per Treiber,
z.B. über Hardwaretimer möglich.timeBeginPeriod sollte jedoch laut Doku dieses Verhalten beeinflusssen.
Von dieser Funktion wusste ich bisher noch nicht.@Dobi
Unter http://msdn.microsoft.com/en-us/library/ms686298(VS.85).aspx
steht etwas mehr zu Sleep, timeBeginPeriod und timeGetDevCaps.Leider auch fast das was ich schon gesagt habe:
"... In my experience, if you set dwMilliseconds to a value greater than 0 but less than one tick (e.g. Sleep(1);), the thread will sleep for at least one tick. So if one tick is 1/64 second (15.625ms), and you Sleep(1);, your thread will (in my experience) sleep for at least 15.625ms ..."
Gruß Frank
-
Sleep(...) kann man prima durch nen Waitable Timer ersetzen:
// Einmal erzeugen: HANDLE waitHandle = CreateWaitableTimer(NULL, true, NULL); // Dieser Teil wäre jeweils unser Sleep()-Aufruf: /////////////////////////////////////////////////// LARGE_INTEGER DueTime; // Hier DueTime setzen (in 100ns Einheiten) // Timer setzen: SetWaitableTimer(waitHandle, &DueTime, 0, NULL, NULL, false); // Auf den Timer warten (frisst keine CPU-Power): WaitForSingleObject(waitHandle,INFINITE); /////////////////////////////////////////////////// // Wenn der Timer irgendwann nicht mehr gebraucht wird, aufräumen: CloseHandle(waitHandle);
...das scheint zumindest auf meinem System gegenüber Sleep() ziemlich genau zu sein. Das Ding kann (wenn man den letzten Parameter bei SetWaitableTimer auf true setzt) scheinbar sogar das System wieder aus dem Standby holen...
-
Hallo geeky,
was ist denn "ziemlich genau" ?
Es geht darum weniger als 15 ms (z.B. 3 ms) zu Warten ohne busy zu laufen.
Danke Gruß Frank
-
Auf meinem System (Win7, 64bit) schafft das scheinbar 1-2ms (allerdings weiss ich nicht ob man dem C# DateTime-Dingen da trauen kann, GetTickCount()-Differenz liefert 0)
-
Frank Erdorf schrieb:
Hallo Dobi,
wie siet dennZeitAusgabeTest
aus ?
Danke, Gruß FrankIch polle ständig die Zeit und gebe sie aus sobald sie sich geändert hat.
lowbyte_ schrieb:
Hi
Denke dass bei dir die Funktion ZeitAusgabeTest(); zu viele Cpu cycles braucht! Daher die schlechte Performance.
LowbyteNein, daran liegt es nicht. Wenn ich nach jedem Pollen ausgebe, habe ich die gleiche Zeit viele Male untereinander stehen und dann den Sprung.
Das Pollen und die Ausgabe verbraucht also wesentlich weniger als die Vierundsechzigstelsekunde._Luckie schrieb:
Warum brauchst du eine so geringe Auflösung?
Ich brauche eine so hohe Auflösung für das Timing bei der Kommunikation mit einer SPS.
@Frank: Mir ist aufgefallen, dass ein Sleep von zb. 10 manchmal aber auch auch schon viel zu früh zurückkommt. Ich vermute mal, dass das passiert, wenn man es ganz kurz vor so einem Zeitsprung aufruft.
@geeky: Werde deinen Vorschlag auch mal ausprobieren und dann berichten.
-
Ich weiß zwar nicht, was eine SPS ist, aber dir sollte bewusst sein, dass Windows kein Echtzeitbetriebssystem ist. Deswegen würde ich das Konzept noch mal überdenken.
-
Hi
Klar ist Windows Echtzeit fähig ! Warum nicht ?
lowbyte
-
Wegen dem Scheduling, du Schlaumeier
-
Hi
Windows ist Echzeitfähig du schlaumeier. Da hilft dir dir ausrede von scheduler auch nicht !!!
Du bist ein schlaumeier Und hasst wohl keine Ahnung.
lowbyte
-
Hi
Klar ist es wegen dem Scheduling nicht möglich genauer als 10ms zu sein. Doch 10ms sind Echtzeit !Und mich musst du nicht Schlaumeier nennen, ich weis von was ich rede ! ok!
Nichts für ungut.
lowbyte