Performance: Die Basis im System

Scheduling

Das Locking-Thema spielt auch bei der Optimierung des Schedulers eine wichtige Rolle. Der Scheduler übernimmt zwei wesentliche Aufgaben:

  • Die Zuweisung von Rechenzeit zu Threads.

  • Die Festlegung, welche Threads auf welchen Prozessoren in einem Mehrprozessor-System ausgeführt werden.

Das Scheduling ist damit vor allem in Mehrprozessorsystemen eine komplexe Herausforderung, weil es hier eben auch noch um die Verteilung von Threads geht. Das betrifft auch Hyperthreading-Prozessoren und Dual-Core-Prozessoren. Bei Ersteren können zwei Threads quasi parallel verarbeitet werden, bei Multi Core-Prozessoren gibt es dagegen zwei oder mehr echte CPUs auf einem Prozessor. Kritisch ist das Locking bei Windows 2000 vor allem in Systemen mit mehr als acht Prozessoren gewesen, die entsprechend auch am stärksten von den Optimierungen beim Locking profitieren. Auch speziell für Hyperthreading-Prozessoren gibt es signifikante Verbesserungen.

Beim Windows Server 2003 hat man versucht, die Locking-Situationen beim Scheduling so weit wie möglich zu vermeiden oder zumindest die Häufigkeit zu reduzieren. Die wichtigste Maßnahme dabei ist, dass viele Warteschlangen und Listen mit zur Ausführung bereiten Threads nun nicht mehr systemweit und damit als globale Variable, sondern pro Prozessor geführt werden.

Im ersten Moment erscheint es zwar so, als könne es dadurch zu einer ungleichmäßigen Auslastung von Prozessoren kommen, weil Anforderungen nicht mehr gleichmäßig verteilt werden. In der Praxis werden Threads aber ohnehin nicht permanent zwischen Prozessoren hin- und hergeschoben, weil das ineffizient wäre, da auch Informationen zu den einem Thread zugeordneten Ressourcen angepasst werden müssten.

Zusätzlich hat man auch einiges an Code modifiziert, um die Phase, in der ein exklusiver Zugriff auf globale Speicherbereiche benötigt wird, zu minimieren. So ist beispielsweise der Code, mit dem die Priorität von Threads erhöht wird, nun so positioniert, dass er außerhalb der globalen Sperrphasen ausgeführt wird. Die Sperre erfolgt hier auf der Ebene des Threads.

Der Windows Server 2003 ist auch für den Einsatz auf Hyperthreading-Prozessoren optimiert. Beim Scheduling wird versucht, Situationen zu vermeiden, in denen Threads um die Ressourcen auf dem gleichen Prozessor konkurrieren. Außerdem wird erkannt, wenn sich einer der beiden logischen Prozessoren auf dem Chip in einem Spinlock befindet. In diesem Fall wird versucht, dem anderen logischen Prozessor möglichst viel Rechenzeit zuzuordnen, statt sie für die Überprüfung von Spinlocks zu vergeuden.

Daneben sind noch einige weitere interessante Verbesserungen für das Scheduling zu nennen, mit denen die Performance des Gesamtsystems erhöht werden soll:

  • Es wird versucht, so genannte Convoys beim Locking zu vermeiden. Convoys – man könnte sie als Stau bezeichnen – entstehen, wenn mehrere Threads mit der gleichen Priorität wiederholt um die gleiche Sperre konkurrieren und diese nur kurz aufrechterhalten. In diesem Fall kann es vorkommen, dass sich eine permanente Warteschlange bildet, wobei durch den Zugriff auf die durch den Lock geschützte Ressource durch unterschiedliche Threads relativ viele Kontextwechsel erforderlich sind, die wiederum Systemressourcen konsumieren (Bild 3).

Bild 3: In bestimmten Situationen kann es zu ineffizienten „Staus“ bei Warteschlangen kommen.
Bild 3: In bestimmten Situationen kann es zu ineffizienten „Staus“ bei Warteschlangen kommen.
  • Optimierungen bei der Arbeitsweise des Timers, mit denen Wartezeiten minimiert werden.

  • Veränderte Verarbeitung von IPIs (Inter-Processor Interrupts), um eine ineffiziente Nutzung des Cache zu vermeiden.

  • Weniger IRQL-Operationen, die durch den Scheduler verursacht werden.

Auch hier waren also eine ganz beachtliche Liste einzelner Veränderungen erforderlich, um die Performance des Gesamtsystems zu erhöhen. Der Schwerpunkt liegt auch in diesem Fall wieder auf Mehrprozessorsystemen mit relativ vielen Prozessoren, weil hier der größte Handlungsbedarf bestand.