Проблема памяти со вставками SQLite на iOS - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть приложение, которое должно делать несколько вставок, считывая значения из файла.Для этого я начинаю транзакцию, подготавливаю оператор, выполняю привязку со значениями (считывается из файла) и выполняю вставку.Все это в цикле для всех строк файла.Все работало нормально, пока я не попробовал файл с миллионом строк.В этом случае я вижу увеличение ОЗУ до сбоя приложения.

Вот как я это реализовал (очевидно, я публикую упрощенный код по моей проблеме, без использования методов, без проверки на ошибки, ecc ..).

sqlite3_stmt *stmt;

// OPEN DATABASE
sqlite3 *db;
if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
    NSLog(@"NON HO APERTO");
}

//BEGIN TRANSACTION
char * sErrMsg = 0;
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
if(sErrMsg != NULL)
    NSLog(@"Error starting transaction");


//PREPARE STATEMENT
char sSQL [BUFFER_SIZE] = "INSERT OR REPLACE INTO table1 (Field2,Field3,Field4,Field5,Field6,Field7,Field8,Field9,Field10,Field11,Field12,Field13,Field14,Field15,Field16,Field17) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
const char * tail = 0;
int res = sqlite3_prepare_v2(db,  sSQL, BUFFER_SIZE, &stmt, &tail);
if(res != SQLITE_OK){
    NSLog(@"Error preparing the statement: %s",sqlite3_errmsg(db));
}

int counter = 0;

//BIND VALUES AND EXEC
FILE * pFile = fopen ([insertsFilePath_test UTF8String],"r");
while (!feof(pFile)) {

    char line [BUFFER_SIZE];
    fgets (line, sizeof(char)*BUFFER_SIZE, pFile);

    NSString* readLine = [NSString stringWithUTF8String:line];

    NSArray *values = [NSJSONSerialization JSONObjectWithData:[readLine dataUsingEncoding:NSUTF8StringEncoding] options:0 error:NULL];
    for(int i = 0; i < [values count];i++){
        int res = sqlite3_bind_text(stmt, i+1, [values[i] UTF8String], -1, SQLITE_TRANSIENT);

        if(res != SQLITE_OK){
            NSLog(@"There is an error with the bind of values: %d error code.",res);
        }
    }
    sqlite3_step(stmt);
    sqlite3_reset(stmt);

    counter++;

    //POINT A


}//while
fclose (pFile);

//END TRANSACTION
char * endTrErrMsg = 0;
sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &endTrErrMsg);
if(endTrErrMsg != NULL){
    NSLog(@"Error closing transaction");
}

sqlite3_finalize(stmt);
sqlite3_close(db);

NSLog(@"FINISH %d",counter++);

Когда я обнаружил проблему, я попытался освободить часть памяти SQLite каждые X строк, добавив в комментарии "// POINT A" что-то вроде:

if((counter % 80000) == 0 ){
  int bytes_freed = sqlite3_release_memory(AMOUNT_OF_MEM_TO_RELEASE);
  NSLog(@"Freed %d",bytes_freed);
  sqlite3_db_release_memory(db);
}

Но "bytes_freed"всегда был 0, и я не увидел даже небольшого изменения в графике оперативной памяти.Я заметил, что после завершения процесса (все строки записаны и соединение с БД закрыто) система освобождает память правильно.Поэтому я попытался закрыть транзакцию, освободить память, завершить оператор, закрыть соединение с БД, снова открыть его, снова подготовить оператор и начать новую транзакцию.Изменение кода в ТОЧКЕ А:

if((counter % 80000) == 0 ){
        char * sErrMsg = 0;
        sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &sErrMsg);
        if(sErrMsg != NULL){
            NSLog(@"Error closing transaction");
        }

        int bytes_freed = sqlite3_release_memory(AMOUNT_OF_MEM_TO_RELEASE);
        NSLog(@"Freed %d",bytes_freed);
        sqlite3_db_release_memory(db);

        sqlite3_finalize(stmt);
        sqlite3_close(db);


        if (sqlite3_open([dbPath UTF8String], &db) != SQLITE_OK) {
            NSLog(@"Error opening db");
        }

        //PREPARE STATEMENT AGAIN
        int res = sqlite3_prepare_v2(db,  sSQL, BUFFER_SIZE, &stmt, &tail);
        if(res != SQLITE_OK){
            NSLog(@"Error preparing the statement: %s",sqlite3_errmsg(db));
        }

        sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &sErrMsg);
        if(sErrMsg != NULL){
            NSLog(@"Error opening transaction");
        }
    }

Ничего не изменилось.Кто-то знает почему?

Кто-нибудь знает, как мне следует столкнуться с проблемой?

...