2010-11-30 5 views
2

私は、制限されたRAMを持つデバイスのC#アプリを書いています。 (モノラルiPhone/iPad上)メモリの再生

私は大きな文字列割り当てる場合:

string xml = "10 meg xml string from REST service"; 

を、クリアそれ

xml = null; 

は、できるだけ早くそのメモリを解放GCでますか?それがきれいにされていることを確認する方法はありますか? GCには収集機能がありますが、これはすぐに実行されますか?

問題は、ループ内に多数の大きなxmlファイルをダウンロードしていて、文字列をnullに設定していてもメモリ使用量が増えていることです。

+1

これは.NET Framework、Compact Framework、またはMicro Frameworkですか? GCの動作はそれらの間で非常に異なります。 –

+0

まあ、それは成長しています。そう?メモリはそれのために使用されるために購入された、それはありませんでしたか? – zerkms

+0

iPhone/iPad上のモノフレーム –

答えて

3

一般的にガベージコレクションが比較的高価であるため、GCはすぐには発生しません。ランタイムは一般的に、他の作業をしていない間に実行しようとしますが、これは必ずしも可能ではありません。私は厳しいメモリ集約的なループを実行している間、GCをあまりにも長く(時には)延期していたので、ある時点でメモリ不足のメモリが不確定になった。レッスン:一般的に、コレクターは自分が何をしているのかを知っていて、それを微調整する必要はありません。しかしいつもではない。

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

EDIT:私はあなたが実行していたものに、あなたのノートを見て前にこれを書いた

が発生するコレクションを強制するには、次の2本のラインを必要とします。これはデスクトップの.NETマシンに基づいて書かれています。モノ/ iPadで異なる場合があります(または違う場合があります)。

+2

GC.Collectをやる必要がある場合は、ひどく間違ったものをコーディングしています。デスクトップGCはセルフチューニングされており、Gen 0が1トンのRAMを吸っていることをすぐに認識し、それに応じて調整します。 GC.Collectを実行すると、このプロセスが短絡されます。 –

+0

iPad/iPhoneのデバイスでMonoですが、それは収集されていないようです。 MonoTouchはフレームワークなどのフレームワークなので、実際にiPhoneで深刻に起こっていることは謎です。デスクトップ上で実行されているこのコードはRAMで正常に動作します。 –

+0

@Bob Palmer - 私はラムを持っていた以上のデータを繰り返していました。通常はうまくいくが、ランダムに(コードを変更せずに)メモリ不足エラーでクラッシュする。いつもクラッシュしたら、私はあなたに同意するでしょうが、クラッシュの完全に非決定論的な性質から、GCがどれくらいうまく機能しているかについて少し過度にナイーブであると思うようになります。 – Donnie

1

私はMonoのエキスパートではありませんが、確認するには簡単なことがいくつかあります。変数をnullに設定していることに気付いたのですが、実際に.Close()または.Dispose()メソッドを適切に呼び出すのか、問題の変数のスコープをusingブロックの中に含めるのですか?

ファイナライザを待っている(つまり、ファイルハンドルのような無秩序なリソースにハンドルを持っている)場合、または何らかの理由で変数がスコープ内にまだ詰まっている場合があります。これにより、メモリ圧が上昇します。

理想的には、明示的に可変スコープを明示的にクリアしてusingブロックと組み合わせる方法でファイルを1つずつ開くようにして、例外がスローされても適切なファイナライザなどが呼び出されるようにします。

希望に役立ちます!

+0

通常、私はCLRプロファイラを使って何が起きているかを見ることをお勧めします - Monoには等価関数がありますが、ヒープで起こっていることをプロファイルするのに使ったことはありません:http://www.mono-project.com/Performance_Tips –

+0

オブジェクトはXMLで塗りつぶす文字列です。私はアプリを実行し、偽の短い文字列に文字列を設定する場合、それは正常に動作します。それは問題を引き起こしている大きな量を得るときです。デスクトップで正常に動作し、メモリは低く保たれます。 –

+0

すぐに死んでしまったり、あまりにも多くの文字列が渡されたりしたのですか? –

2

まず、大きな文字列や大きな配列をメモリに一度に保存することは避けてください。特に携帯電話のようなメモリに制約のあるデバイスでは避けてください。たとえば、XmlTextReaderを使用してxmlファイルを解析します。

次にガベージコレクションに関する問題:現在のMono GCはスレッドスタックを慎重にスキャンします。つまり、オブジェクトへのポインタがまだ静的である可能性があります。 (たとえあなたの例ではnullに設定されているように)プログラマーにクリアされていても、GCに見えるようにしてください。 この動作の結果を制限するには、大規模な配列と文字列を別々のスタックフレームに割り当てたり操作したりしてください。たとえば、代わりにそれをこのようにコーディング:

while (true) { 
    string s = get_big_string_from_network(); 
    do_something_with_string(s); 
    handle_ui(); 
    s = null; 
    } 

を行う次

void manipulate_big_string() { 
    string s = get_big_string_from_network(); 
    do_something_with_string(s); 
    } 
    ... 
    while (true) { 
    manipulate_big_string(); 
    handle_ui(); 
    } 

通常は、NULLへの参照を設定すると、使用して、静的またはインスタンスフィールドに適用されるのみ意図された効果を有していますメソッドローカル変数を使用すると、GCから参照を非表示にするには不十分な場合があります。

2

iPhone用に開発している場合は、.netフレームワークのgargabeコレクタを持っていないと思います。メモリ管理は、オペレーティングシステム(この場合はiOS)によって行われます。

この場合、メモリの管理方法を調べるには、モノドキュメントをチェックインする必要があります。 XCodeが実装され、自動参照カウントと呼ばれる自動オブジェクト管理は、.NET Frameworkのようなガベージコレクションではなく、未使用のオブジェクトを解放するための自動ツールにすぎません。

大きな文字列を扱うときに.netだけを考えているので、文字列の代わりに常にstringbuilderを使うべきです。

iOSで考えてみると、iOS環境用に書かれたアプリとWindows用のデスクトップアプリケーション(あなたはもっと多くのリソースがあります)を比較する必要はありません。 iOSはメモリ消費量を大幅に減らすことはできません。アプリがこれを行うと、オペレーティングシステムは自動的にシステムを停止してシステムを動作させます。

関連する問題