MonoTouch-Instabilität wird fortgesetzt: Verwalteter Speicherzuordner stürzt ab

8

Lange Redewendung: Ich kann tonnenweise nicht verwalteten Speicher zuweisen, aber wenn ich versuche, dieselbe Menge (oder weit weniger) im verwalteten Speicher zuzuweisen, stürzt MonoTouch in GC_remap ab (Aufruf unten).

Details:

Ich werde über ein Beispiel des oben beschriebenen Verhaltens sprechen. Meine App vergibt gelegentlich einen 2,5 MB großen Teil des verwalteten Speichers (mit neuem byte []), der oft auf meinem iPhone4 mit dem unten eingefügten Callstack endet (d. H. Mprotect error während der Zuweisung). Ich behalte einen Verweis auf diese 2,5 MB Blöcke nicht länger als einen einzelnen Funktionsaufruf.

Die MonoTouch-Leute sagen, dass 'mprotect errno 12' bedeutet, dass du ' Speicher auf Ihrem Gerät erschöpft zu sein , aber die Sache ist, ich habe viel Speicher für meine App verfügbar. Ich kann 0 MB , 10 MB oder 200 MB unmanaged Speicher (mit Marshal.AllocHGlobal) beim Start meiner App zuordnen , berühre es jeden Frame, und es macht keinen Unterschied im Verhalten meiner App oder in der Häufigkeit dieses mprotect-Fehlers.

Einige Notizen

  • GC.TotalMemory teilt mir mit, dass meine App ständig zwischen 3MB und 5MB der verwalteten Speicherbelegung sitzt.
  • Ich habe andere Orte in meiner App, wo ich noch größere Blöcke von unmanaged Speicher zuweise, und es stürzt dort nie ab. Ich habe Stresstests erstellt, die 4MB (nicht verwaltete) Texturdaten laden, an den GL übergeben und jeden Frame zeichnen, und die App ist felsenfest, bis ich nach großen Blöcken von verwaltetem Speicher
  • GC.CollectionCount ändert sich kaum, wenn ich GC.Collect nicht selbst anrufe.
  • Dasselbe Verhalten tritt bei MonoTouch 3.2.3 sowie bei MonoTouch 4.0 auf.
  • Dasselbe Verhalten passiert bei allen unseren Testgeräten (iPhone 3G, 3GS, 4, iPad, iPad2).
  • Dasselbe Verhalten tritt bei Release-Builds und Debug-Builds auf, obwohl es häufiger bei Debug-Builds auftritt.

Möglichkeiten, den Absturz zu provozieren

  • Wenn ich einen Thread erzeuge, der den Aufruf von GC.Collect umschlingt und dann für 1 ms schläft, wird der Absturz viel früher passieren (d. h. praktisch sofort, wenn ich in einem Debug-Build bin).
  • Die Verwendung bestimmter .NET-Funktionen wie WebRequest führt ebenfalls zu diesem Absturz. Ich kann nur annehmen, dass es auch dort große Blöcke verwalteten Speichers verteilt.

Wege um den Absturz herum

Es gibt zwei Möglichkeiten, die Häufigkeit des Absturzes zu reduzieren oder zu beheben:

  1. Wenn ich diesen 2,5 MB großen Teil des gemanagten Speichers VORZUWEISE und ihn dann für die gesamte Lebensdauer der App bereithalte, dann gibt es keinen Absturz.
  2. Wenn ich den 2,5MB großen Speicherblock anhefte, bevor ich irgendetwas damit mache, scheint das zu helfen.

Schlussfolgerungen / Fragen

Aufgrund dieses Problems müssen wir die volle Stabilität in unserer App erreichen. Dieser Absturz (immer innerhalb von GC_remap) passiert in zufälligen Zuweisungen in unserer App (das 2.5MB Beispiel, das ich hier habe, ist nur das, das ich zu isolieren und zu repro).

Fragen:

  1. Kann ich dem verwalteten Allokator überhaupt nicht vertrauen?
  2. Warum kann ich 200 MB nicht verwalteten Speicher zuweisen, aber der verwaltete Zuordner wird gelöscht, wenn ich nach 2,5 MB frage? (Hinweis: Es wird sterben, wenn ich nach 2,5 MB frage, auch wenn ich nicht die 200 MB nicht verwalteten Speicher zugewiesen habe).
  3. Warum ist die App völlig in Ordnung, wenn ich diese 2.5MB für die Lebensdauer der App hasse, aber wenn ich sie dem System zurückgebe (und GC.Collect anrufe) und nach weiteren 2.5MB später frage, dann wird die Krach ist schlimmer! Wenn dies wirklich ein niedriger Speicherzustand ist, sollte es nicht besser sein, 2,5 MB zurück an das System zu geben, als es zu speichern?

Können wir sogar MonoTouch verwenden?

Mein Team erwägt ernsthaft, MonoTouch für unser Produkt aufzugeben, weil wir es nicht zuverlässig stabil machen können.

Wir können die Uhrzeit auch nicht vom MonoTouch-Team im Stack-Overflow abrufen, indem wir Fehler auf der Novell-Website einreichen oder die Support-E-Mail von MonoTouch direkt per E-Mail senden. Wir haben unsere (verwaltete und nicht verwaltete) Speicherbelegung auf lächerliche Tiefstwerte reduziert, aber die App ist aufgrund dieses Problems immer noch unruhig.

Kurzfristig ist die einzige Problemumgehung, die ich mir vorgenommen habe, ein großer Speicherblock (2-5MB) beim Start zu reservieren, PIN so, dass der Müllsammler es nie berührt, und meinen eigenen Zuordner für dole zu schreiben teile Teile dieses Speicherblocks nach Bedarf zu meiner App aus. Aber wenn dies die beste Lösung ist, die unter MonoTouch möglich ist, werde ich mein Geld zurückbekommen, sobald ich die Escape-Geschwindigkeit von MonoTouch erreichen kann.

...

%Vor%     
Mike 14.04.2011, 17:06
quelle

1 Antwort

1

Der Darwin-Kernel überbrückt Speicher.

Das heißt, wenn Sie 200 MB RAM anfordern, werden Sie sie erhalten, auch wenn sie nicht verfügbar sind, und solange Sie den Speicher nicht wirklich verbrauchen, wird Ihre Anwendung ausgeführt gut.

Nur wenn Sie tatsächlich auf die Seite schreiben, wird die Seite Ihrem Prozess zugewiesen.

Ein richtiger Test würde erfordern, dass Sie den Speicher zuweisen und dann den belegten Speicher auffüllen, deshalb haben Sie wahrscheinlich den Eindruck, dass Sie 200 MB Ram selbst dann zuweisen können, wenn Sie es nicht einmal haben.

Ein einfaches Programm zeigt Ihnen das: Versuchen Sie 500 MEG zuzuweisen, das Betriebssystem wird sagen "Ja, Sie haben es", aber es gibt keine iPhones mit dieser Art von Speicher.

Ein Beispiel-Testfall würde einen langen Weg zeigen, um zu zeigen, was das Problem ist.

    
miguel.de.icaza 14.04.2011 23:20
quelle