0

私はディスクからファイルを読み取り、それを行ごとに分離し、それをに格納してから、NSArrayその配列をループして、データに対してかなり基本的な操作を実行しようとしています。ただし、小さいファイル(〜5000行のデータ、1行に1ワード)を使用している場合、ループの終わりまでに数百メガバイトのメモリを使用することになります。非常に大きなファイル(〜200,000行)を使用している場合、数ギガバイトのメモリを使用することになります。なぜこれが起こるのですか?ファイルをアレイにロードすると、メモリの最初のスパイクが表示されるはずですが、その後、メモリ使用量はかなり一定に保たれるはずです。私はARCを使用していましたが、それを信用していなかったので、今はすべてのメモリ管理を自分で行っており、ループで割り当てたすべての一時的なものを解放していると確信しています。

NSString *fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

NSScanner *scanner = [NSScanner scannerWithString:fileContents];
NSMutableArray *wordList = [[[NSMutableArray alloc] init] autorelease];
while (![scanner isAtEnd]) {
    NSString *line = [[NSString alloc] init];
    [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&line];
    [wordList addObject:line];
    [line release];
}
return wordList;
4

2 に答える 2

4

2つの問題があります。文字列を不必要に作成しているので、ループから文字セットの作成を引き上げる必要があります。スキャナーはおそらく一時的なオブジェクトも作成しています。また、内部自動解放プールをループに追加する必要があります。

NSMutableArray *wordList = [[[NSMutableArray alloc] init] autorelease];
NSCharacterSet * newline = [NSCharacterSet newlineCharacterSet];
while (![scanner isAtEnd]) {
    @autoreleasepool{
        NSString *line;
        [scanner scanUpToCharactersFromSet:newline intoString:&line];
        [wordList addObject:line];
    }
}

文字列は単なる古いリークです。scanUpToCharactersFromSet:intoString:割り当てられた文字列を要求せず、その後、その文字列への参照を失いました-は、release割り当てたものと同じインスタンスをターゲットにしていません。ただし、ここで割り当てられるメモリの量はそれほど重要ではないということは、リチャードの言うとおりです。

文字セットに関しては、ループ中に自動解放プールが排出されないため、newlineCharacterSet呼び出すたびに新しいインスタンスを作成して自動解放する場合は、そこにもメモリが蓄積されます。NSCharacterSetそれがあなたのためにそれをキャッシュするのに十分賢いことを願っていますが、文字列プログラミングガイドのメモ:

  • 文字セットを継続的に再作成するのではなく、(おそらくグローバルディクショナリに)キャッシュします。

そうではないかもしれないことを示唆している。

ただし、私の3つの提案の中で最も効果的なのは、内部自動解放プールである可能性があります。

最後に、ARCを使用します。それは機能し、文字列と文字セットの問題を処理していたでしょう。

于 2013-01-23T18:22:42.303 に答える
0

このコードでは多くのことが起こっているという事実を考慮に入れる必要があります。

まず、NSObjectsを使用しているため、これらのオブジェクトへのポインタ、関数、仮想関数テーブルなどを格納するために、おそらく多くのオーバーヘッドが発生します。それに加えて、10,000個のnullで終了する文字列があります。また、NSMutableArrayがあります。これは、実装方法によっては、割り当てられたスペースの最大半分を空にして、新しい要素があるたびにNSMutableArrayのサイズを増やすのではなく、追加の要素を追加できるようにすることができます。

コードのメモリ効率を本当に高めたい場合は、文字列に文字配列を使用しchar *、単語のリストを格納するために配列を使用することを検討してください。また、Instrumentsの使用に関する「Catfish_Man」のアドバイスに従うことをお勧めします。

お役に立てれば!幸運を!

于 2013-01-23T18:42:05.743 に答える