Windows 7: Überschießen C ++ std :: this_thread :: sleep_for

8

Unser Code ist in C ++ 11 geschrieben (VS2012 / Win 7-64bit). Die C ++ - Bibliothek stellt eine sleep_for -Funktion zur Verfügung, die wir verwenden. Wir haben beobachtet, dass das C ++ sleep_for manchmal ein großes Überschwingen zeigt. Mit anderen Worten, wir bitten um etwa 15 ms zu schlafen, aber der Schlaf stellt sich z.B. 100 ms. Wir sehen das, wenn die Systemlast hoch ist.

Meine erste Reaktion: "Natürlich dauert das" länger ", wenn das System stark belastet wird und andere Threads die CPU nutzen". Die "lustige" Sache ist jedoch, dass wir dieses Verhalten nicht sehen, wenn wir den sleep_for durch einen Windows API "Sleep" -Aufruf ersetzen. Ich habe auch gesehen, dass die Funktion sleep_for unter Wasser einen Aufruf an die Methode Window API Sleep aufruft.

Die Dokumentation für sleep_for lautet:

  

Die Funktion blockiert den aufrufenden Thread für mindestens die Zeit, die durch Rel_time angegeben wird. Diese Funktion löst keine Ausnahmen aus.

Also technisch funktioniert die Funktion. Wir haben jedoch keinen Unterschied zwischen C ++ sleep_for und der regulären Sleep(Ex) -Funktion erwartet.

Kann jemand dieses Verhalten erklären?

    
user3773903 02.10.2015, 09:34
quelle

1 Antwort

2

Bei Verwendung von sleep_for vs. SleepEx wird ziemlich viel zusätzlicher Code ausgeführt.

Wenn Sie beispielsweise SleepEx (15) aufrufen, wird die folgende Assembly im Debug-Modus (Visual Studio 2015) generiert:

%Vor%

Im Gegensatz dazu dieser Code

%Vor%

Erzeugt Folgendes:

%Vor%

Dies ruft auf:

%Vor%

Und ruft in

auf %Vor%

Eine Konvertierung geschieht:

%Vor%

Schließlich wird die importierte Funktion aufgerufen, dieselbe, die SleepEx verwendet hat.

%Vor%

Sie sollten sich auch darüber im Klaren sein, dass SleepEx möglicherweise nicht 100% genaue Ergebnisse liefert, wie in der MSDN Dokumentation Ссылка

Diese Funktion bewirkt, dass ein Thread den Rest seiner Zeitscheibe abgibt und für ein Intervall basierend auf dem Wert von dwMilliseconds nicht mehr ausführbar ist. Die Systemuhr "tickt" mit konstanter Rate. Wenn dwMilliseconds kleiner als die Auflösung der Systemuhr ist, kann der Thread für weniger als die angegebene Zeitdauer schlafen. Wenn dwMilliseconds größer als ein Tick, aber kleiner als zwei ist, kann die Wartezeit zwischen einem und zwei Ticks liegen und so weiter. Um die Genauigkeit des Schlafintervalls zu erhöhen, rufen Sie die timeGetDevCaps-Funktion auf, um die unterstützte minimale Timerauflösung zu ermitteln, und die timeBeginPeriod-Funktion, um die Timerauflösung auf das Minimum zu setzen. Seien Sie vorsichtig beim Aufruf von timeBeginPeriod, da häufige Anrufe die Systemuhr, den Stromverbrauch des Systems und den Scheduler erheblich beeinflussen können. Wenn Sie timeBeginPeriod aufrufen, rufen Sie es früh in der Anwendung auf und stellen Sie sicher, dass die Funktion timeEndPeriod am Ende der Anwendung aufgerufen wird.

    
Malcolm McCaffery 06.10.2015 06:42
quelle

Tags und Links