0

データベースに挿入する必要のある行がたくさんあります。必要な情報でタブ区切りされた約50個の.txtファイルをダウンロードします。データを解析し、同じ方法でデータベースに挿入します。別のメソッドとして使用した場合、27インチiMacのシミュレータは、メモリが不足したためにクラッシュしました。メソッドは次のようになります。

- (BOOL)insertDataWithFileName:(NSString *)fileName {
    NSLog(@"%s %@", __FUNCTION__, fileName);
    if (_db == nil) {
        return NO;
    }
    // Get the data from the file
    NSData *data = [[NSData alloc] initWithContentsOfFile:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:fileName]];
    NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    // Parse each line by newlines first
    NSArray *lines = [responseString componentsSeparatedByString:@"\n"];        

    NSString *ID = [[fileName componentsSeparatedByString:@"."] objectAtIndex:0];

    // Set up the database insert statement
    NSString *tableName = @"Hardcodedtablename"; // remove after prototype
    BOOL oldshouldcachestatements = _db.shouldCacheStatements;
    [_db setShouldCacheStatements:YES];
    [_db beginTransaction];
    NSString *insertQuery = [NSString stringWithFormat:@"INSERT INTO %@ values(null, ?, ?, ?, ?, ?, ?, ?);", tableName];
    BOOL success;

    // Parse each line by tabs
    for (NSString *line in lines) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSArray *fields = [line componentsSeparatedByString:@"\t"];

        // Need to check since some of the .txt files have an empty newline at the EOF.
        if ([fields count] == NUM_VARIANT_FIELDS) {
            NSNumber *loc = [NSNumber numberWithInteger:[[fields objectAtIndex:0] integerValue]];       
            NSString *carType = [fields objectAtIndex:1];
            NSString *model = [fields objectAtIndex:2];
            NSString *AA = [fields objectAtIndex:7];
            NSString *BB = [fields objectAtIndex:8];

            NSNumber *freq = [[fields objectAtIndex:11] isEqualToString:@""] ? [NSNumber numberWithDouble:-1.0] : [NSNumber numberWithDouble:[[fields objectAtIndex:11] doubleValue]];

            NSArray *argArray = [[NSArray alloc] initWithObjects:ID, loc, carType, model, AA, BB, freq, nil];

            success = [_db executeUpdate:insertQuery withArgumentsInArray:argArray];
            [argArray release];

        }
        [pool drain];
    }

    [_patientAnnotatedDatabase commit];
    [_patientAnnotatedDatabase setShouldCacheStatements:oldshouldcachestatements];

    return success;
}

forループからわかるように、配列が\ tで区切られた後は、実際には配列内のすべてのファイルは必要ありません。forループのメモリフットプリントを減らすために自動解放プールを設定しました。最大のファイルには270,000行が含まれています。これらのファイルは約50個あります。そのため、デバイスに2つのファイルを保存すると、クラッシュします。ただし、エラーメッセージはありません。

この時点で自分の選択肢は何だったのだろうと思っていました。iPadは実際にその量のデータを処理できますか?この方法を最適化できますか?

または、サーバー側でデータベースを作成し、代わりにデータベースをデバイスにダウンロードする必要がありますか?データベースをサーバーからデバイスにダウンロードした場合、FMDBは、これらのテーブルを1つのDBから別のDBに転送する機能をサポートしていますか?グーグルをしている間、そのようなものを見つけることができませんでした。ありがとう!

4

2 に答える 2

0

それは、データを何に使用しているかによって大きく異なります。検索に使用する場合、または本当にすべてが必要な目的で使用する場合、基本的にこの量のメモリを使用しています。

270,000 rows * 25 chars/row * 50 files * 1 byte/char = 321 Mb of RAM

25文字/行の部分くらいだと推測していますが、100Mb以上のメモリを使用している場合は、大量のメモリを使用しています。ただし、iPadには約 1GB の RAM が搭載されているため、使用可能なメモリ量の範囲内に収まっているように見えます。しかし、それを格納するために使用している NSArrays と SQLite FMDB のもの (および他の NSObjects) のため、カプセル化されたデータは、iPad で実行されている他のプロセスに追加されると、1GB を超える可能性があります。

したがって、このすべてのメモリが問題になる可能性があります。このすべてのデータを、それを処理できる Web サーバーに保存し、そのサーバーを介して必要な関数を呼び出す方がよい場合があります。おそらくはるかに高速で、更新が必要な場合はデータを簡単に調整できます。また、十分な RAM を搭載していない iPhone などのデバイスでもアプリを使用できるようになります。

膨大な量のデータが問題である場合、解決策は上記のものです。ただし、iPad は 300 MB 以上の RAM を処理できると私は信じているので、問題はコードにある可能性があります。特にデータをファイルから配列に分離する場合は、すべてのデータに正しくアクセスしていることを確認してください。最小の「境界外」配列エラーがプログラムの失敗を引き起こす可能性があるためです。

また、メモリ プロファイラを有効にしてコードを実行してみましたか。「Profiler」というオプションを選択できるようになるまで「実行」の丸いボタンを押し続けることで、新しい Xcode でこのアプリを有効にすることができます。このアプリは、アプリが使用しているメモリの量を表示するので、1GB 未満であることを確認できます。

于 2012-07-23T00:47:41.810 に答える
0

残念ながら、以前のバグを追跡するために、スキームで NSZombieEnabled をオンに設定しました。オフにすると、現時点ではクラッシュしていないようです。

于 2012-07-23T19:41:08.303 に答える