2012-09-01 18 views
6

Jeśli użyję następującego połączenia w C++, oczekiwałbym, że WorkingSet procesu nigdy nie spadnie poniżej 100 MB.Czy istnieje sposób zmusić WorkSet procesu do 1GB w C++?

Jednak system operacyjny nadal przycina zestaw roboczy z powrotem do 16 MB, nawet jeśli wykonam to połączenie.

Ustawienie zestawu roboczego na 100 MB doprowadziłoby do dramatycznego zwiększenia szybkości aplikacji, eliminując błędy stronicowania strony (zobacz poniższy diagram).

Co robię źle?

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 dla ekspertów)Experimental Metodologia

Napisałem testowy C++ projekt przeznaczyć 100MB danych w celu doprowadzenia WorkingSet ponad 100MB (patrząc w ciągu Process Explorer), a następnie zwalniane że pamięć. Jednak system operacyjny zdemontował WorkingSet z powrotem do 16 MB, gdy tylko zwolniłem tę pamięć. Mogę dostarczyć testowy projekt C++, którego użyłem, jeśli chcesz.

Dlaczego system Windows wywołuje funkcję SetProcessWorkingSetSizeEx(), jeśli nie działa? Muszę robić coś złego.

Poniższy diagram pokazuje dramatyczny wzrost liczby błędów stronicowania (czerwonych impulsów), gdy zielona linia (zestaw roboczy) spadła z 50 MB do 30 MB.

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

Aktualizacja

W końcu skończyło się na ignorowanie problemu, gdyż nie wpłynąć na wydajność, że dużo.

Co ważniejsze, SetProcessWorkingSetSizeEx robi nie kontrolę prądu WorkingSet i jest nie związanych w jakikolwiek sposób z miękkich błędów stron. Wszystko, co robi, to zapobieganie ciężkim awariom stron, uniemożliwiając przeniesienie bieżącego WorkSet na dysk twardy.

Innymi słowy, jeśli chcemy zmniejszyć błędy stronicowania, funkcja SetProcessWorkingSetSizeEx nie ma żadnego efektu, ponieważ odnosi się do poważnych błędów stronicowania.

Istnieje świetny zapis w "Windowsie przez C/C++" (Richter), który jak Windows zajmuje się pamięcią.

+1

Jak można oczekiwać, że system operacyjny będzie przechowywać więcej stron w pamięci niż zostało przez Ciebie przydzielone? –

+0

@James McNellis Jeśli system operacyjny mógłby zachować więcej stron w zestawie roboczym, liczba błędów stron zmniejszyłaby się, co znacznie przyspieszyłoby program. Na serwerze mamy 16 GB wolnej pamięci RAM i nie zaszkodzi mieć 1GB na stałe przypisanym do tego procesu (co zmniejszyłoby liczbę błędów stronicowania do 0). – Contango

+0

@Gravitas: Jak alokować pamięć i uzyskiwać do niej dostęp? – ybungalobill

Odpowiedz

4

Usterki strony są tanie i należy się spodziewać. Aplikacje działające w czasie rzeczywistym, gry z najwyższej półki, przetwarzanie o wysokiej intensywności i odtwarzanie BluRay działają z pełną szybkością z błędami stron. Błędy strony nie są powodem, dla którego aplikacja działa wolno.

Aby dowiedzieć się, dlaczego aplikacja jest wolna, należy wykonać profilowanie aplikacji.

Aby w konkretny sposób odpowiedzieć na pytanie - błędy strony występujące, gdy właśnie GC.Collect() nie są błędami stronicowania, są to błędy stronicowania ze względu na żądanie spowodowane faktem, że GC właśnie przydzielił nowy, ogromny blok stron o zerowym zapotrzebowaniu, aby przenieść swoje obiekty. Strony zerowe zapotrzebowania nie są obsługiwane z pliku stronicowania i nie ponoszą żadnych kosztów dysku, ale nadal są to błędy stron, dlatego pokazują się na wykresie.

Zgodnie z ogólną zasadą system Windows lepiej zarządza zasobami systemowymi niż użytkownik, a jego ustawienia domyślne są bardzo dobrze dostosowane do przeciętnego przypadku normalnych programów. Z twojego przykładu jasno wynika, że ​​używasz garbage collectora, a więc już przeładowałeś zadanie zajmowania się zestawami roboczymi i pamięcią wirtualną itd. Do implementacji GC. Jeśli SetProcessWorkingSetSize było dobrym połączeniem API w celu poprawy wydajności GC, to byłoby to możliwe dzięki implementacji GC.

Moja rada to profil aplikacji. Główną przyczyną spowolnienia w zarządzanych aplikacjach jest pisanie źle zarządzanego kodu, a nie GC spowalniającego. Popraw efektywność swoich algorytmów, odłóż kosztowną pracę za pomocą takich rzeczy, jak Future i BackgroundWorker i staraj się unikać synchronicznych żądań do sieci - ale przede wszystkim kluczem do szybkiego uzyskania aplikacji jest profil .

+0

Użyliśmy Microsoft Concurrency Visualizer, aby uzyskać wgląd w to, co dzieje się w aplikacji. W końcu strata wydajności nie była wystarczająca, aby się martwić. – Contango

Powiązane problemy