10

私のアプリケーションは、私が作成したプロセス中に、メモリ内で上昇しており、解放されていないようです。

最初に言及したいのは、私が書いたものの基本的な概要は次の とおり
です

データがデコードされたFMDBフレームワークを使用して、sqliteデータベースにレコードを挿入/更新/削除するNSArray

アプリケーションは上記を実行しますが、アプリケーションが「ロード中」の HUD を表示する不定期間のループで実行します。これについて言及する価値があるかもしれないと思いましたが、適切に解放されていればメモリ使用量に影響を与えないはずなので、このプロセスを何回実行するかは重要ではありません。ここで間違っている場合は、教えてください。

私のコードは問題なく動作します。意図したとおりに動作します。ただし、アプリケーション コードをプロファイリングすると、メモリが増え続けているように見えます。全体的にセグメントが低下していますが、全体的には上昇し続けています (IE は以前使用していたものを完全にはリリースしません)。

前述のように、割り当て、リーク、VM トラッカーを使用してアプリケーションをプロファイリングし、Trace Highlights を使用しました。

Trace Highlights : メモリ使用量が徐々に増加していることを示していますが、一部のメモリ (すべてではない) が低下しています。つまり、プロセスが長時間実行されている場合、メモリの使用率が高くなり、終了します。

割り当て: OK のようです。割り当てにはスパイクがありますが、常に開始した場所に戻ります。私はヒープショットを撮りましたが、それらは常にドロップダウンし、セグメントごとに最大500〜700kbを残します(約10分間放置)

VM トラッカー: メモリが一貫して増加し、完全なメモリを解放していないことを示していることが証明されています (トレースのハイライトで発見)。居住者は本当に高くなるようです

漏れ: アプリケーションに漏れはありません

実行中の割り当て/VM トラッカーのスクリーンショットを次に示します。
ここに画像の説明を入力 ここに画像の説明を入力

私が実際に試したことは注目に値し ます
:
NSURL、NSRequest など。無に

私の質問:
- メモリを解放するために何か特別なことをする必要がありますか?
- この問題をさらにデバッグするにはどうすればよいですか?
- Instruments から提供されたデータから何が問題なのかを知るにはどうすればよいですか?

----編集: ----
データを取得するための URL 要求を送信するコードは次のとおりです。

- (void) requestAndParse : (NSString *)url 
{
    NSURL *theURL;
    ASIHTTPRequest *request;
    NSData *collectedData;
    NSError *error;
    @try {
                    // File cache the NSData
                    theURL = [[NSURL alloc] initWithString: url];
                    request = [ASIHTTPRequest requestWithURL: theURL];
                    [request setDownloadDestinationPath: [[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]];
                    [request startSynchronous];
                    [request waitUntilFinished];

                    collectedData = [[NSData alloc] initWithContentsOfFile:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"]];


                    if ([collectedData length] > 0) {
                        records = [NSJSONSerialization JSONObjectWithData:collectedData options:NSJSONReadingMutableContainers error:&error];
                    }

    }
    @catch (NSException *exception) {

                    // Failed
                    NSLog(@"Parse error: %@", error);

    }
    @finally {

                    // DB updates with the records here
                    ...

                    // remove file
                    [[NSFileManager defaultManager] removeItemAtPath:[[NSHomeDirectory() stringByAppendingPathComponent:@"Documents"] stringByAppendingString:@"/cachefile.txt"] error:nil];
                    // release properties used
                    collectedData = nil;
                    request = nil;
                    theURL = nil;
    }

}

この上記のメソッドは、アプリケーション デリゲートの while ループ内から呼び出されます。前述のように、while ループの長さは不定です。

--- 編集 2: ---

以下は、@finally ステートメント内で行われることです (FMDB を使用して SQLite データベースを更新します)。私のクラスには、テーブルごとに 1 つずつ、これらのメソッドがたくさんあります。ただし、それらはすべて最初のものから複製されているため、すべて同じパターンに従います。

-(BOOL) insertBatchOfRecords:(NSArray *)records {

__block BOOL queueReturned = YES;

@autoreleasepool {

    FMDatabaseQueue *dbQueue = [self instantiateDatabaseQueue];
    [dbQueue inTransaction:^(FMDatabase *tdb, BOOL *rollback) {
        if (![tdb open]) {
            NSLog(@"Couldn't open DB inside Transaction");
            queueReturned = NO;
            *rollback = YES;
            return;
        }

        for (NSDictionary *record in records) {
            [tdb executeUpdate:@"INSERT OR REPLACE INTO table (attr1, attr2) VALUES (?,?)", [record valueForKey:@"attr1"], [record valueForKey:@"attr2"]];

            if ([tdb hadError]) {
                queueReturned = NO;
                *rollback = YES;
                NSLog(@"Failed to insert records because %@", [tdb lastErrorMessage]);
                return;
            }
        }
    }];

    [dbQueue close];
    dbQueue = nil;

}

return queueReturned;
}

以下は -instantiateDatabaseQueue メソッドです。

-(FMDatabaseQueue *) instantiateDatabaseQueue {
@autoreleasepool {
    return [FMDatabaseQueue databaseQueueWithPath: [self.getDocumentsDirectory stringByAppendingPathComponent:@"localdb.db"]];
}
}

autoreleasepools によって面倒になる可能性がありますが、コードには元々これらがありませんでした。改善があるかどうかを確認するために、さまざまな場所にそれらを実装しました(ありませんでした)。

--- 編集 3 ---

ここ数日、アプリケーションのプロファイリングを行ってきましたが、まだ答えが見つかりません。問題のアプリの部分を独自の別のプロジェクトに分離して、実際にこれがメモリ使用量の原因であることを確認しました。アプリはまだ同じように動作しているため、これは正しいことが証明されました.

私はさらにプロファイリング写真を撮りましたが、実際に何が間違っているのかを特定するのにまだ苦労しています. 以下を参照してください。割り当ては問題ないように見えます (VM も私にはそれほど悪くないように見えますか?)、まだリークはありません (何もないため、この画像はありません!!)。

ただし、Trace Highlights でプロファイリングすると、メモリの使用量が増え続け、使用量が多すぎる (3GS で約 70 MB 以上) に達し、大量のメモリを使用するためにクラッシュします。

ここに画像の説明を入力

ここに画像の説明を入力

ここに画像の説明を入力

ここに画像の説明を入力

ここに画像の説明を入力

NSData を取得するために ASIHTTPRequest を使用することで問題を軽減しました (代わりにファイルに保存します)。上記の修正されたコードを参照してください。ただし、問題は解決せず、発生するまでに時間がかかります。

当初の質問:
- このアプリ プロセスの 2 番目の部分に何か問題がありますか?

4

1 に答える 1