2010-03-12 3 views
8

ich diese Ausnahme zu diagnostizieren versuchen:System.Runtime.InteropServices.COMException (0x80070008): nicht genügend Speicher verfügbar, um diesen Befehl zu verarbeiten

System.Runtime.InteropServices.COMException (0x80070008): Not enough storage is available to process this command. (Exception from HRESULT: 0x80070008) 
at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType) 
at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(Type objectType) 
at System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(Type serverType) 
at System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(Type serverType, Object[] props, Boolean bNewObj) 
at Oracle.DataAccess.Client.CThreadPool..ctor() 
at Oracle.DataAccess.Client.OracleCommand.set_CommandTimeout(Int32 value) 
... 

Es sieht nicht wie eine des normalen Typs von " Speicher "haben keine Grenzen gesetzt. Die Anwendung verwendet ungefähr 400 MB Speicher, 70 Threads, 2000 Griffe und die Festplatte hat viele GB frei. Die Maschine läuft Windows 2003 Enterprise Server 32bit mit 16 GB RAM, so Speicher sollte kein Problem sein.

Die Anwendung wird als Windows-Dienst ausgeführt, sodass keine GDI-Objekte verwendet werden. Das Ausführen von GDI-Handles ist eine häufige Ursache dieser Ausnahme.

Datenbankverbindungen, Befehle & Leser sind alle mit Blöcken verpackt, so dass sie richtig aufgeräumt werden sollten.

UPDATE: Reduzieren der Anzahl der Threads, die wir von 12 bis 4 verwendeten, scheint das Problem behoben zu haben. Wir haben es über 24 Stunden geschafft, ohne Fehler zu laufen, bevor wir zwischen 4 und 8 Stunden dauerten. UPDATE2: Ich habe nie herausgefunden, auf welche Ressource wir keinen Zugriff hatten, aber die Anzahl der Threads zu reduzieren scheint das Problem zu beheben. Oder zumindest versteckte es.

+1

Ist es ein 64-Bit-Prozess? – SLaks

+0

Shot in der Dunkelheit (seyying Interop) rufen Sie Marshal.ReleaseComObject? –

+1

@Marvin: Die Interop wird von Oracle gemacht. – SLaks

Antwort

0

Sieht so aus, als würde etwas zu viele Objekte auf dem Heap loopen und instanziieren, so dass der Speicher auf dem Heap nicht mehr ausreicht. Suchen Sie nach Loops im aufrufenden Code.

+0

Eigentlich vergiss es, Googeln lässt es so aussehen, dass dies ein Oracle-Speicherproblem auf 32-Bit-Maschinen ist, also bezweifle ich, dass ich im Moment helfen kann. –

6

Ein weiterer Faktor, den Sie berücksichtigen müssen, ist die Speicherfragmentierung.

Die maximale einzelne Zuweisung, die Sie ausführen können, entspricht dem größten zusammenhängenden Speicherblock, der für den Prozess verfügbar ist. Dies ist wegen der Fragmentierung fast immer geringer als die gesamte Speichermenge, die im Prozess verfügbar ist. Das sind zugeteilte Speicherblöcke, die zwischen zwei freien Speicherblöcken sitzen und den Speicher "fragmentieren".

Je mehr Fragmentierung Sie haben, desto kleiner ist der größte zusammenhängende Speicherblock, der verfügbar sein wird. Ich habe Situationen gesehen, in denen fast 1 GB Speicher frei war, aber der größte zusammenhängende Block war ungefähr 10 MB groß.

Haben Sie in diesem Prozess nach Speicherfragmentierung gesucht?

+0

Gibt es Ratschläge zum Erkennen von Speicherfragmentierung? Ich versuche derzeit DebugDiag Speicherleck-Erkennung gegen den Prozess auf einem Testserver ausgeführt wird. –

+0

Fragmentierung scheint kein Problem zu sein, der größte freie Block war 500 MB, während die Anwendung Probleme hatte. Dies wurde mit dem Tool sysinternals vmMap erfasst. –

2

Sie haben alle offensichtlichen Fehlerquellen für Ihren Prozess beseitigt. Macht es wahrscheinlich, dass dies tatsächlich ein Betriebssystemproblem ist. Die einzige Ressource, die auf einem Server immer unter Druck steht, ist der Kernel-Speicherpool. Es ist leicht zu sehen, TaskMgr.exe zeigt es auf der Registerkarte Leistung an.

Es stimmt etwas mit Ihrem Call-Stack überein, sieht so aus, als ob der Oracle-Provider Threads für einen Thread-Pool erstellt. Ein Thread benötigt in Ihrem Prozess ein Megabyte. und 24 KB im Kernelspeicherpool, der als Stapel verwendet wird, wenn der Thread in den Kernelmodus wechselt.

Hintergrundinformationen sind available here.

+0

Dies scheint nicht das Problem zu sein, da es über 40 MB freien Nicht-Seiten-Pool und 100 MB ausgelagerten Pool gibt. Ich habe mir auch die Perfmon-Zähler für alle "Objects" -Ereignis-Semaphore usw. angeschaut und wir scheinen diese auch nicht zu verlieren. –

+0

Nun, Zeit, Oracle einen Anruf zu geben. –