Frage

Es scheint, dass in Vista / Windows Server 2008 führt zu dem Betriebssystem nicht vollständig zurückzugewinnen die Speicher Kritische Abschnitte ziemlich viel verwenden. Wir haben dieses Problem mit einer Delphi-Anwendung, und es ist klar, da die CS-API. (Siehe diese SO Frage )

Hat sonst noch jemand mit Anwendungen gesehen mit anderen Sprachen (C ++, ...) entwickelt?

Das Codebeispiel wurde initialzing nur 10000000 CS, löscht sie dann. Dies funktioniert in XP / Win2003 in Ordnung, aber entbindet nicht alle Spitzenwertspeicher in Vista / Win2008, bis die Anwendung beendet wird.
Je mehr Sie CS verwenden, desto mehr Ihre Anwendung behält Speicher für nichts.

War es hilfreich?

Lösung

Microsoft hat in der Tat die Art und Weise verändert InitializeCriticalSection auf Vista funktioniert, Windows Server 2008 und wahrscheinlich auch Windows 7.
Sie fügten hinzu, ein „Feature“ etwas Speicher für Debug-Informationen verwendet zu halten, wenn Sie eine Reihe von CS zuordnen. Je mehr Sie zuweisen, desto mehr Speicher erhalten. Es könnte sein, asymptotisch und schließlich abflachen (nicht vollständig zu diesem gekauft).
Um dieses „Feature“ zu vermeiden, müssen Sie die neue API verwenden InitalizeCriticalSectionEx und die Flagge CRITICAL_SECTION_NO_DEBUG_INFO passieren.
Der Vorteil davon ist, dass es schneller sein könnte, wie sehr oft nur die spincount werden, ohne tatsächlich wartet verwendet werden.
Die Nachteile sind, dass Ihre alte Anwendungen nicht kompatibel sein können , müssen Sie Ihren Code ändern, und es ist jetzt plattformabhängig (Sie müssen für die Version zu überprüfen, welche zu benutzen, um zu bestimmen). Und Sie auch die Fähigkeit verlieren, zu debuggen, wenn Sie benötigen.


:

Testkit einen Windows Server 2008 einzufrieren - Erstellen dieses C ++ Beispiel als CSTest.exe

#include "stdafx.h" 
#include "windows.h" 
#include <iostream> 

using namespace std; 

void TestCriticalSections() 
{ 
  const unsigned int CS_MAX = 5000000; 
  CRITICAL_SECTION* csArray = new CRITICAL_SECTION[CS_MAX];  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    InitializeCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    EnterCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    LeaveCriticalSection(&csArray[i]);  

  for (unsigned int i = 0; i < CS_MAX; ++i)  
    DeleteCriticalSection(&csArray[i]); 

  delete [] csArray; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
  TestCriticalSections(); 

  cout << "just hanging around..."; 
  cin.get(); 

  return 0; 
}

-... Führen Sie diese Batch-Datei (benötigt die sleep.exe vom Server SDK)

@rem you may adapt the sleep delay depending on speed and # of CPUs 
@rem sleep 2 on a duo-core 4GB. sleep 1 on a 4CPU 8GB. 

@for /L %%i in (1,1,300) do @echo %%i & @start /min CSTest.exe & @sleep 1 
@echo still alive? 
@pause 
@taskkill /im cstest.* /f

-... und sieht einen Win2008 Server mit 8 GB und Quad-CPU-Kern Einfrieren bevor die 300-Instanzen gestartet erreichen.
-... auf einem Windows 2003 Server wiederholen und es damit umgehen wie ein Zauber sehen.

Andere Tipps

Ihr Test ist wahrscheinlich nicht repräsentativ für das Problem. Kritische Abschnitte werden als „leichte mutexes“, weil ein echter Kernel-Mutex nicht erstellt, wenn Sie den kritischen Abschnitt initialisieren. Dies bedeutet, dass Ihre 10M kritische Abschnitte sind nur structs mit ein paar einfachen Mitglieder. Wenn jedoch zwei Threads eine CS zur gleichen Zeit zugreifen, um synchronisieren sie ein Mutex tatsächlich erstellt wird -. Und das ist eine andere Geschichte

Ich gehe davon aus in Ihren realen App Fäden kollidieren, wie auf Ihren Test-App gegenüber. Nun, wenn Sie wirklich kritische Abschnitte als leichte mutexes Behandlung und eine Menge von ihnen erstellen, Ihre Anwendung kann eine große Anzahl von realen Kern mutexes werden Zuteilung, die sind viel schwerer als das Licht kritischen Abschnitt Objekt. Und da mutexes ist Kernel-Objekt, eine übermäßige Anzahl von ihnen zu schaffen wirklich dem O verletzen kann.

Wenn dies tatsächlich der Fall ist, sollten Sie die Verwendung von kritischen Abschnitten reduzieren, wo Sie eine Menge von Kollisionen erwarten. Das hat nichts mit der Windows-Version zu tun, so meine Vermutung falsch sein könnte, aber es ist noch etwas zu prüfen. Versuchen Sie die Überwachung der OS Griffe zählen, und sehen, wie Ihre Anwendung tut.

Du siehst etwas anderes.

Ich habe gerade gebaut und lief diesen Test-Code. Jede Speichernutzung Stat konstant -. Privates Bytes, Arbeitssatz, verpflichten, und so weiter

int _tmain(int argc, _TCHAR* argv[])
{
    while (true)
    {
        CRITICAL_SECTION* cs = new CRITICAL_SECTION[1000000];
        for (int i = 0; i < 1000000; i++) InitializeCriticalSection(&cs[i]);
        for (int i = 0; i < 1000000; i++) DeleteCriticalSection(&cs[i]);
        delete [] cs;
    }

    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top