6 Stimmen

Wie begrenzt man die CPU-Auslastung eines Prozesses unter Windows (benötigt Code, keine Anwendung)?

Es gibt Programme, die in der Lage sind, die CPU-Auslastung von Prozessen in Windows zu begrenzen. Zum Beispiel BES y ThreadMaster . Ich muss mein eigenes Programm schreiben, das das Gleiche tut wie diese Programme, aber mit anderen Konfigurationsmöglichkeiten. Weiß jemand, wie die CPU-Drosselung eines Prozesses durchgeführt wird (Code)? Ich spreche nicht von der Einstellung der Priorität eines Prozesses, sondern eher davon, wie man seine CPU-Nutzung auf z.B. 15% begrenzt, auch wenn es keine anderen Prozesse gibt, die um CPU-Zeit konkurrieren.

Aktualisierung: Ich muss in der Lage sein, alle Prozesse zu drosseln, die bereits laufen und auf die ich keinen Zugriff auf den Quellcode habe.

10voto

Jerry Coffin Punkte 452852

Wahrscheinlich möchten Sie den/die Prozess(e) in einem Job-Objekt ausführen und die maximale CPU-Auslastung für das Job-Objekt mit SetInformationJobObject , mit JOBOBJECT_CPU_RATE_CONTROL_INFORMATION .

4voto

Damon Punkte 64271

Sehr vereinfacht könnte es so funktionieren:

  1. Erstellen Sie einen periodisch wartenden Timer mit einer vernünftig kleinen Wartezeit (vielleicht 100ms). Holen Sie einen "letzten" Wert für jeden relevanten Prozess, indem Sie GetProcessTimes einmal.
  2. Endlosschleife, Blockierung des Timers.
  3. Jedes Mal, wenn Sie aufwachen:
    • si GetProcessAffinityMask 0 zurückgibt, rufen Sie SetProcessAffinityMask(old_value) . Das bedeutet, dass wir diesen Prozess in unserer letzten Iteration angehalten haben und ihm nun eine Chance geben, erneut zu laufen.
    • sonst aufrufen GetProcessTimes um den "aktuellen" Wert zu erhalten
    • aufrufen GetSystemTimeAsFileTime
    • Berechnung des Deltas durch Subtraktion des letzten vom aktuellen Wert
    • cpu_usage = (deltaKernelTime + deltaUserTime) / (deltaTime)
    • wenn das mehr ist, als Sie wollen aufrufen old_value = GetProcessAffinityMask gefolgt von SetProcessAffinityMask(0) was den Prozess offline schaltet.

Dies ist im Grunde eine sehr primitive Version des Schedulers, der im Kernel läuft und im Userland implementiert ist. Er versetzt einen Prozess für eine kleine Zeitspanne "in den Schlaf", wenn er mehr CPU-Zeit verbraucht hat, als Sie für richtig halten. Eine ausgefeiltere Messung, die vielleicht über eine Sekunde oder 5 Sekunden hinausgeht, wäre möglich (und wahrscheinlich wünschenswert).

Sie könnten versucht sein, stattdessen alle Threads des Prozesses zu unterbrechen. Es ist jedoch wichtig no mit den Prioritäten zu spielen und no zu verwenden SuspendThread wenn Sie nicht genau wissen, was ein Programm tut, da dies leicht zu Deadlocks und anderen unangenehmen Nebeneffekten führen kann. Denken Sie zum Beispiel daran, einen Thread anzuhalten, der einen kritischen Abschnitt hält, während ein anderer Thread noch läuft und versucht, dasselbe Objekt zu erwerben. Oder stellen Sie sich vor, Ihr Prozess wird mitten in der Suspendierung von einem Dutzend Threads ausgelagert, so dass die Hälfte von ihnen läuft und die andere Hälfte tot ist.

Wenn die Affinitätsmaske auf Null gesetzt wird, bedeutet dies lediglich, dass von nun an kein einzelner Thread des Prozesses mehr Zeitscheiben auf einem beliebigen Prozessor erhält. Das Zurücksetzen der Affinität gibt - atomar, zur gleichen Zeit - allen Threads die Möglichkeit, wieder zu laufen.

Unglücklicherweise, SetProcessAffinityMask gibt die alte Maske nicht als SetThreadAffinityMask tut, zumindest laut der Dokumentation. Daher ist eine zusätzliche Get... Anruf notwendig ist.

0voto

Carey Gregory Punkte 6735

Die CPU-Nutzung lässt sich recht einfach schätzen, indem man QueryProcessCycleTime . Die Prozessorgeschwindigkeit der Maschine kann über HKLM abgerufen werden \HARDWARE\DESCRIPTION\System\CentralProcessor\\ ~MHz (wobei die Prozessornummer angegeben wird, ein Eintrag für jeden vorhandenen Prozessor). Mit diesen Werten können Sie die CPU-Auslastung Ihres Prozesses abschätzen und die CPU bei Bedarf mit Sleep() entlasten, um die Auslastung in Grenzen zu halten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X