Ist 16 Millisekunden eine ungewöhnlich lange Zeit, bis ein nicht blockierter Thread unter Windows ausgeführt wird, um auf die Ausführung zu warten?

StackOverflow https://stackoverflow.com/questions/8322826

Frage

Kürzlich habe ich einige tiefe Timing -Überprüfungen in einer DirectShow -Anwendung durchgeführt, die ich in Delphi 6 mit den DSpack -Komponenten habe. Im Rahmen meiner Diagnostik habe ich eine kritische Abschnittsklasse erstellt, die dem üblichen kritischen Abschnittsobjekt, das in den meisten Windows-Programmiersprachen zu finden ist, eine Time-Out-Funktion hinzufügt. Wenn die Zeitdauer zwischen dem Erste Erwerben () und die Letzte Matching Release () ist mehr als X Millisekunden, eine Ausnahme wird ausgelöst.

Anfangs habe ich die Auszeit auf 10 Millisekunden gestellt. Der Code, den ich in kritische Abschnitte eingewickelt habe, wird für die meisten in den geschützten Bereichen enthaltenen Vorgänge ziemlich schnell und füllt die meist Speicherbewegungen. Zu meiner Überraschung bekam ich ziemlich häufige Auszeiten in scheinbar zufälligen Teilen des Codes. Manchmal geschah es in einem Codeblock, der eine Pufferliste iteriert und bestimmte schnelle Operationen nacheinander ausführt, manchmal in winzigen Abschnitten geschützter Codes, die nur eine Löschung eines Flaggen zwischen den Anrufen von Acquire () und Release () durchgeführt haben. Das einzige Muster, das ich bemerkte, ist, dass die Dauer, die beim Auftreten der Auszeit gefunden wurden, auf einen mittleren Wert von etwa 16 Millisekunden gezogen wurden. Offensichtlich ist das eine große Menge an Zeit, dass eine Flagge in letzterer Beispiel eines oben erwähnten Auftretens festgelegt wird.

Also meine Fragen sind:

1) Ist es möglich, dass Windows Thread Management -Code auf ziemlich häufige Basis (ungefähr alle paar Sekunden) einen nicht blockierten Thread ausschaltet und nicht für 16 Millisekunden oder länger dorthin zurückkehrt?

2) Wenn das ein vernünftiges Szenario ist, welche Schritte kann ich unternehmen, um dieses Ereignis zu verringern, und sollte ich in Betracht ziehen, meine Fadenprioritäten zu erhöhen?

3) Wenn es sich nicht um ein vernünftiges Szenario handelt, wie sollte ich dann noch als Analysetechnik ansehen oder versuchen, um das eigentliche Problem zu diagnostizieren?

Hinweis: Ich leite auf Windows XP auf einem Intel i5 Quad Core mit 3 GB Speicher. Der Grund, warum ich in diesem Code schnell sein muss, liegt auf der Größe des Puffers in Millisekunden, die ich in meinen DirectShow -Filtergraphen ausgewählt habe. Um die Latenz bei minimalen Audiopuffern in meinem Diagramm zu halten, werden alle 50 Millisekunden geliefert. Daher ist jeder Betrieb, der einen erheblichen Prozentsatz dieser Zeitdauer erfordert, beunruhigend.

War es hilfreich?

Lösung

Thread -Prioritäten bestimmen, wann die Fadenfäden ausgeführt werden. Es gibt jedoch einen Mechanismus zur Verhinderung von Hunger. Es gibt einen sogenannten Balance-Set-Manager, der jede Sekunde aufwacht und nach vorbereitenden Threads sucht, die seit etwa 3 oder 4 Sekunden lang nicht mehr ausgeführt wurden. Wenn es einen gibt, wird es seine Priorität auf 15 erhöhen und ihm ein doppeltes den Normales Quanten. Dies geschieht für nicht mehr als 10 Threads gleichzeitig (pro Sekunde) und scannt nicht mehr als 16 Threads auf jeder Prioritätsebene gleichzeitig. Am Ende des Quantums sinkt die gesteigerte Priorität auf seinen Grundwert. Sie können mehr in den Windows -Interna -Buch (n) erfahren.

Es ist also ein ziemlich normales Verhalten, das Sie beobachten, Threads können Sekunden lang nicht ausgeführt werden.

Möglicherweise müssen Sie Prioritäten erhöhen oder andere Themen auf andere Weise berücksichtigen, die um die CPU -Zeit konkurrieren.

Andere Tipps

Klingt nach einem normalen Windows -Verhalten in Bezug auf die Timerauflösung, es sei denn, Sie entscheiden sich ausdrücklich für einige der hochpräzisen Timer. Einige Details in Dieser MSDN -Link

Zunächst bin ich mir nicht sicher, ob Delphi's Now ist eine gute Wahl für Millisekunden -Präzisionsmessungen. GetTickCount und QueryPerformanceCoutner API wäre eine bessere Wahl.

Wenn es keine Kollision in der kritischen Abschnittssperrung gibt, läuft alles ziemlich schnell. Wenn Sie jedoch versuchen, einen kritischen Abschnitt zu betreten, der derzeit auf einem anderen Thread gesperrt ist, treffen Sie schließlich einen Wartevorgang auf einem internen Kernelobjekt (Mutex oder Ereignis), das, welche Beinhaltet die Steuerung des Threads und wartet darauf, dass Scheduler später die Kontrolle zurückgibt.

Das "spätere" obige "später" würde von einigen oben genannten Dingen abhängen, einschließlich der oben genannten Prioritäten, und es gibt eine wichtige Dinge, die Sie in Ihrem Test weggelassen haben - was ist die gesamte CPU -Last zum Zeitpunkt Ihres Tests. Je mehr die Ladung ist, desto weniger Chancen, den Thread die Ausführung bald fortzusetzen. 16 ms Zeit sieht vielleicht ein bisschen immer noch in angemessener Toleranz aus, und insgesamt kann es von Ihrer tatsächlichen Implementierung abhängen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top