NT Cache Setter
 
English Version of this page
 
  Allgemeines
 
Unter Windows NT, Windows 2000 und XP kann der Festplatten-Cache theoretisch den gesamten Hauptspeicher einnehmen. Die Obergrenzen sollen unter NT4 bei 512 MB und unter 2000/XP bei 960 MB liegen. Ich habe es unter XP mit 2 GB RAM aber nicht geschafft, das Cache-Working-Set auf über 512 MB zu bekommen.
Nicht selten hat man den Eindruck, dass der Speicher laufender Programm zugunsten eines großen File-Caches ausgelagert wird. Braucht man das Programm dann wieder, kann man zusehen und zuhören, wie es aus dem Pagefile gebuddelt wird...
Unter Windows 9x konnte man das vermeiden indem man in der SYSTEM.INI die Maximalgröße des Caches limitiert hat. Unter NT, 2000 und XP fehlt diese Möglichkeit.

Richtig schlimm wird es, wenn von einem Windows Optimierungs-Tool oder auf einen schlauen Ratschlag hin 'LargeSystemCache' auf 1 gesetzt wurde. Das heißt soviel wie "wenn Windows Speicher braucht, möge es sich den irgendwo holen, aber nicht beim File-Cache"...

Einzige Möglichkeit, auf die Größe des File-Cache Einfluss zu nehmen ist, dessen 'Working-Set' zu trimmen. Das Working-Set ist der Speicher, den der Besitzer kürzlich benutzt hat, von dem Windows also erwartet, dass er demnächst wieder benutzt wird und der deshalb nach Möglichkeit nicht ausgelagert werden sollte. Jeder Prozess hat ein Working Set, auch der Cache.
Das Working-Set zu trimmen heißt nicht, dass der Speicher freigegeben oder verworfen wird. Das Working Set eines Programms wird z.B. auch getrimmt, wenn man es minimiert: Man sehe sich die Spalte 'Speichernutzung' im XP-Taskmanager an wenn man eine Anwendung minimiert (manche Anwendungen umschiffen das, z.B. Firefox wenn trim_on_minimize=0 gesetzt ist). Ab Vista zeigt der Taskmanager standardmäßig die tatsächliche Speichernutzung, das Workingset der Prozesse wird beim korrekten Namen genannt.

Mit dem SysInternals-Tool CacheSet kann man das Working-Set des File-Caches beobachten und auf Knopfdruck trimmen.
Wie gesagt wird durch das Trimmen nichts verworfen - der Speicher steht dem Cache nach wie vor zur Verfügung. Auch wenn das Working-Set nicht wächst, heißt das nicht, dass nur genau so viel Cache benutzt wird. Er wird nur bei Bedarf eher verworfen, um den freigewordenen Speicher anderen Bedarfsträgern zur Verfügung zu stellen. Genaugenommen gehört der Cache, der nicht Teil des Cache-Working-Sets ist, zum freien Speicher. Er wird nur sinnvoll genutzt, solange er nicht anderweitig gebraucht wird.

 

  Windows NT, 2000, XP
 
Um den File-Cache etwas unter Kontrolle zu bekommen, habe ich auf Basis des Quelltextes von CacheSet meinen NtCacheSetter geschrieben, der das Trimmen des Working-Sets des File-Caches regelmäßig ausführt.

Beispiel für die Kommandozeile:

NtCacheSet /int=1s /min=8M /max=64M /show=1
/int setzt den Interval in Millisekunden oder mit Einheit s auf n Sekunden

/min ist der Minimum-Wert des Working-Sets in Bytes oder mit Einheit KiB, MiB, GiB (K, M, G reichen auch)

/max ist der Maximum-Wert des Working-Sets in Bytes oder mit Einheit KiB, MiB, GiB (K, M, G reichen auch)

Standard-Werte bei Start ohne Kommandozeile:
- Interval: 1 Sekunde
- Maximum: 1/16 des Hauptspeichers - Minimum: 1/4 des Maximums - Show: 0 (Fenster nicht zeigen)

NtCacheSet nochmal gestartet, beendet es die vorherige Instanz.

Das periodische Trimmen erfolgt nur wenn die aktuelle Größe das gewählte Maximum um 10% überschreitet, da jedes Trimmen das System kurz ausbremst. Im Fenster wird das durch die "LED" signalisiert:
Grau: Ruhe
Grün: Werte geprüft, kein Handlungsbedarf
Rot : Werte geprüft und Cache-Einstellungen gesetzt
Zum Testen verschiedener Werte kann man auf diese klicken und neue eingeben. Ja, das ist schlechtes GUI-Design.

Ich kann nicht versprechen, dass das Tool sinnvoll ist - aber ich denke schon, spätestens seit Microsoft bei Windows 2003 Server SP1 die Funktion SetSystemFilecacheSize eingeführt hat, s. unten. Periodisches Trimmen ist aber eine Notlösung: Ist der Intervall zu lang, kann Windows das Cache-Working-Set zwischenzeitich doch wieder zu Lasten von Anwendungen wachsen lassen, mit einem kurzen Intervall wird etwas CPU-Last generiert.

Interessant ist dieser (englische) Artikel aus dem Buch "Windows 2000 Performance Guide":
File Cache Performance and Tuning

 

  Windows 2003 Server, Vista, Windows 7/8/10, Server 201x
 
Mit dem Service Pack 1 für Windows 2003 Server hat Microsoft eine neue API-Funktion eingeführt, mit der sich das Working Set des File-Caches permanent limitieren läßt: SetSystemFilecacheSize.

Daraus habe ich ein gleichnamiges Tool gemacht. Ohne Kommandozeilenparameter zeigt es eine Messagebox mit den aktuellen Werten. Um Einstellungen vorzunehmen, muss es "als Administrator" und mit entsprechenden Kommandozeilenparametern gestartet werden:

Beispiele für die Kommandozeile:

SetSystemFilecacheSize
Zeigt die aktuellen Einstellungen

SetSystemFilecacheSize /?
Zeigt diese Hilfe

SetSystemFilecacheSize 8 128
Setzt die minimale Größe auf 8 MB und die maximale auf 128 MB

SetSystemFilecacheSize off 128
Deaktiviert die minimale Größe und setzt die maximale auf 128 MB

SetSystemFilecacheSize off off
Deaktiviert minimale und maximale Größe

SetSystemFilecacheSize flush
'flusht' den File-Cache

Das Tool zeigt eine Message-Box wenn nötig, sonst bleibt es unsichtbar und gibt Errorlevel 0 zurück.

Für Werte > 4096 MB auf x64 Systemen muß die x64-Version benutzt werden.

Im Gegensatz zu Sysinternals CacheSet bewirkt SetSystemFilecacheSize ein permanente Limitierung der Größe des Working-Sets des File-Caches.
Das Working-Set zu limitieren heißt nicht, dass der Cache nicht größer werden kann als dieses Limit. Begrenzt ist nur das Working-Set des Caches. Wenn ausreichend freier Speicher vorhanden ist, wird der Cache auch größer. Das Limitieren des Working-Sets bewirkt nur, dass das Working-Set laufender Prozesse nicht zu Gunsten des Caches zusammengestrichen und deren Speicher in der Folge ausgelagert wird.
Mit dem Windows 10 Update 1703 hat SetSystemFilecacheSize keine Wirkung mehr, deshalb habe ich den alten NT Cache Setter aktualisiert, siehe oben.
Mit Update 1709 funktioniert es wieder.

 

  Microsoft
 
Inzwischen hat sich auch Microsoft des Problems angenommen:
http://support.microsoft.com/kb/976618.

 

  Verhalten des Windows File-Cache und wie man es testet
 
Zum Testen des File-Caches habe ich ein weiteres kleines Tool geschrieben:
FileCacheTest
Mit einem parallel laufenden CacheSet kann man die Auswirkungen auf das Working-Set des File-Caches beobachten.

FileCacheTest schreibt in oder liest aus einer Datei und nutzt dabei verschiedene Optionen (Flags) der dafür zuständingen Win32-API-Funktion CreateFile. Hier die Bedeutung der Flags - alle Beobachtungen sind unter XP SP2 und LargeFileCache=0 gemacht.

Kein Flag:
Windows macht keine speziellen Annahmen und der Working-Set bleibt unauffällig. Daten werden gecached.

FILE_FLAG_RANDOM_ACCESS:
Windows nimmt zufällige Zugriffsmuster an, meint daher, es müsse das Workig-Set des Caches aggresiv aufblasen und ggf. das Working-Set von Anwendungen zusammenstreichen und deren Speicher auch gerne mal auslagern. Später kann man dann zusehen wie insbesondere zwischenzeitlich minimierte Anwendungen - offenbar ohne jede Optimierung - aus dem Pagefile gebuddelt werden (beim Minimieren wird das Working-Set einer Anwendung auf Null getrimmt - zu sehen auch im Task-Manager).
Vistas "ReadyBoost" soll dieses Symptom lindern...
Für Software-Entwickler: Dieses Flag nur mit großer Vorsicht nutzen! Sich auf den Windows File-Cache zu verlassen heißt nichts weiter, als das was man selbst machen kann, einem Automatismus zu überlassen. Pfui!
Nero6 scheint es beim Schreiben einer Image-Datei zu nutzen. Macht ja auch Sinn - die Zugriffe sind total zufällig...

FILE_FLAG_SEQUENTIAL_SCAN:
Windows nimmt sequenzielle Zugriffe an. Auf den ersten Blick keine große Wirkung. Wahrscheinlich werden alte Cache-Blöcke schneller wieder verworfen und es wird Wert auf das Vorrauslesen gelegt.

FILE_FLAG_NO_BUFFERING:
Windows arbeitet vollständig am Cache vorbei - so liest und schreibt man große Dateien am schnellsten! Daten werden direkt zwischen Datenträger und dem Datenpuffer in der Anwendung transferiert - es sei denn die Datei ist NTFS-komprimiert. Das 'no buffering' scheint sich nur auf die Daten selbst und nicht auf den Verzeichniseintrag zu beziehen. Hakt man in der Testanwendung 'flush at end' an, gibts auch hier noch eine kurze Pause. Möglicherweise weist Windows hier tatsächlich die Festplatte zum Leeren ihres internen Caches an. Wer weiß mehr?
Für Software-Entwickler: Der Puffer in der Anwendung muß eine Startadresse haben die ein ganzzahliges Vielfaches der Sektorgröße des Datenträgers ist. Auch die Anzahl der zu lesenden oder zu schreibenden Bytes muß ein Vielfaches der Sektorgröße sein. Den Puffer bekommt man am einfachsten, indem man sich den Speicher per VirtualAlloc holt. Das liefert 64K aligned Speicher - das ist ok für alle bekannten Sektorgrößen (2K bei CD/DVD, neuerdings 4K bei einigen Festplatten). In C/C++ geht auch _aligned_malloc. Am Dateiende muß man beim Schreiben ggf. mit SetFilePointer und SetEndOfFile korrigieren.

FILE_FLAG_WRITE_THROUGH:
Schreibzugriffe gehen durch den Cache, aber auch in den Cache - folgende Lesezugriffe kommen also u.U. aus dem Cache.
Außderdem wird physische Datenträger angewiesen, eventuell vorhandenen Cache nicht zu benutzen, also direkt auf den Datenträger zu schreiben, bzw. am Ende des Schreibens sofort zu Leeren.

Mit 'flush at finish' wird nach dem Ende des Schreibens der File-Cache 'geflusht', also zum sofortigen Leeren angewiesen. Wurde kein Schreib-Cache benutzt, ist die 'flush time' gleich oder nahe Null. Das ist z.B. der Fall, wenn man auf einen FAT-formatierten USB-Stick schreibt - auch dann, wenn für ihn dank Richtlinie 'Für Geschwindigkeit optimieren' angeblich ein Schreibcache aktiv sein soll. Die Einstellung hat aber seit sie mit XP eingeführt wurde bei USB-Wechseldatenträgern keinerlei meßbare Wirkung. siehe auch meine Tips zu USB-Sticks. Erst wenn man mit der Blockgröße auf unter 4096 Bytes geht, bekommt man einen Schreibcache, wie gehabt unabhängig von o.g. Richtlinien. So kann man locker mal 20 MB Daten in den Schreibcache eines 'Zum schnellen Entfernen optimierten' USB-Sticks blasen. Bei NTFS-formatierten USB-Wechseldatenträgern liegt die magische Grenze bei einer Blockgröße von ca. 512 KB. Je langsamer der USB-Stick umso deutlicher der Effekt.

Mit "create and delete files" werden leere Dateien angelegt und anschließend gelöscht. So wird deutlich, ob Schreibzugriffe auf's Dateisystem gepuffert werden oder nicht.

 


 
 
  Download
 

NtCacheSetter, SetSystemFilecacheSize und FileCacheTest sind Freeware.

Download NtCacheSetter V0.4:
ntcacheset.zip

Die VB6 Runtimes werden benötigt. Sie sind bei NT4-SP5, W2K, XP, Vista, Windows 7/8/10 und den Servern schon dabei.

Download SetSystemFilecacheSize V0.3:
SetSystemFilecacheSize.zip

Download FileCacheTest:
FileCacheTest.zip

 


letzte inhaltliche Änderung: 17.04.2017

Uwe Sieber