2012-09-01 10 views
6

Wenn ich den folgenden Aufruf in C++ verwende, würde ich erwarten, dass das WorkingSet des Prozesses nie unter 100 MB fallen würde.Gibt es eine Möglichkeit, das WorkingSet eines Prozesses 1 GB in C++ zu erzwingen?

Allerdings schneidet das OS den Arbeitssatz immer noch auf 16MB zurück, auch wenn ich diesen Aufruf mache.

Die Einstellung von WorkingSet auf 100 MB würde zu einer dramatischen Steigerung der Anwendungsgeschwindigkeit führen, da Fehler auf der Seite der Seitenfehler vermieden werden (siehe Diagramm unten).

Was mache ich falsch?

SIZE_T workingSetSizeMB = 100; 
int errorCode = SetProcessWorkingSetSizeEx(
    GetCurrentProcess(), 
    (workingSetSizeMB - 1) * 1024 * 1024), // dwMinimumWorkingSetSize 
    workingSetSizeMB * 1024 * 1024, // dwMaximumWorkingSetSize, 
    QUOTA_LIMITS_HARDWS_MIN_ENABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE 
); 
// errorCode returns 1, so the call worked. 

(extra für die Experten)Experimental Methodology

I einen Test C++ Projekt schrieb 100 MB Daten zuzuteilen die WorkingSet über 100MB zu bringen (wie in Process Explorer betrachtet), ausgeplant dann, dass Erinnerung. Das Betriebssystem hat das WorkingSet jedoch auf 16 MB reduziert, sobald ich diesen Speicher freigegeben habe. Ich kann das Test C++ Projekt zur Verfügung stellen, das ich verwendete, wenn Sie wünschen.

Warum bietet Windows einen Aufruf von SetProcessWorkingSetSizeEx() an, wenn es nicht zu funktionieren scheint? Ich muss etwas falsch machen.

Das folgende Diagramm zeigt die dramatische Zunahme der Anzahl der Soft-Page-Fehler (die roten Spitzen), wenn die grüne Linie (der Arbeitssatz) von 50 MB auf 30 MB abgefallen ist.

Example showing the increase in soft page faults when the WorkingSet is reduced too low

aktualisieren

Am Ende landeten wir ignorieren das Problem auf, da es nicht die Leistung viel, die einen Einfluss haben.

Noch wichtiger ist, tut SetProcessWorkingSetSizeEx nicht Kontrolle der aktuellen WorkingSet und ist nicht in irgendeiner Weise im Zusammenhang mit weichen Seitenfehler. Es verhindert nur harte Seitenfehler, indem verhindert wird, dass das aktuelle WorkingSet auf die Festplatte ausgelagert wird.

Mit anderen Worten, wenn Sie Soft-Page-Fehler reduzieren möchten, hat SetProcessWorkingSetSizeEx absolut keine Wirkung, da es sich auf Hard-Page-Fehler bezieht.

Es gibt eine tolle Beschreibung in "Windows via C/C++" (Richter), wie Windows mit Speicher umgeht.

+1

Wie erwarten Sie, dass das Betriebssystem mehr Seiten im Speicher hält als Sie zugewiesen haben? –

+0

@James McNellis Wenn das Betriebssystem mehr Seiten im WorkingSet behalten könnte, würde die Anzahl der Seitenfehler abnehmen, was das Programm erheblich beschleunigen würde. Wir haben 16GB freien RAM auf dem Server, und es wäre nicht schaden, 1GB dauerhaft diesem Prozess zugewiesen zu haben (was die Anzahl der Soft-Page-Fehler auf 0 reduzieren würde). – Contango

+0

@Gravitas: Wie reservieren und greifen Sie auf den Speicher zu? – ybungalobill

Antwort

4

Seitenfehler sind billig und zu erwarten. Echtzeit-Anwendungen, High-End-Spiele, High-Intensity-Processing und BluRay-Wiedergabe arbeiten bei Seitenfehlern mit voller Geschwindigkeit. Seitenfehler sind nicht der Grund, warum Ihre Anwendung langsam ist.

Um herauszufinden, warum Ihre Anwendung langsam ist, müssen Sie ein Anwendungsprofil Ihrer Anwendung erstellen.

Um speziell Ihre Frage zu beantworten - die Seitenfehler, die auftreten, wenn Sie gerade eine GC.Collect() haben, sind keine Seitenfehler, die durch die Nullung von Seiten verursacht werden GC hat gerade einen neuen großen Block von nach Bedarf auf Null gesetzten Seiten zugewiesen, auf den Ihre Objekte verschoben werden können. Anforderungsnullseiten werden nicht von Ihrer Auslagerungsdatei verarbeitet und verursachen keine Datenträgerkosten, aber sie sind immer noch Seitenfehler, weshalb sie in Ihrem Diagramm angezeigt werden.

Als allgemeine Regel gilt, dass Windows Ihre Systemressourcen besser verwaltet als Sie selbst, und die Standardwerte sind stark auf den Durchschnitt von normalen Programmen abgestimmt. Aus Ihrem Beispiel geht eindeutig hervor, dass Sie einen Garbage-Collector verwenden, und daher haben Sie bereits die Aufgabe ausgelagert, mit Arbeitssätzen, virtuellem Speicher usw. zur GC-Implementierung umzugehen. Wenn SetProcessWorkingSetSize ein guter API-Aufruf zur Verbesserung der GC-Leistung war, würde die GC-Implementierung dies tun.

Mein Rat an Sie ist, Ihre App zu profilieren. Der Hauptgrund für die Verlangsamung in verwalteten Anwendungen ist das Schreiben von schlecht verwaltetem Code - nicht der GC verlangsamt Sie. Verbessere die große O-Leistung deiner Algorithmen, verliere teure Arbeit durch die Verwendung von Dingen wie Future und BackgroundWorker und versuche synchrone Anfragen an das Netzwerk zu vermeiden - aber vor allem ist der Schlüssel, um deine App schnell zu bekommen, Profil es .

+0

Wir haben Microsoft Concurrency Visualizer verwendet, um einen Einblick zu bekommen, was in der App passiert. Am Ende war der Leistungsverlust nicht ausreichend, um sich Sorgen zu machen. – Contango

Verwandte Themen