GCD-> bloques-> C ++ -> SQLCipher: La memory Sqlite3MemMalloc no se libera después de completar la tarea

Estoy trabajando en la aplicación de bases de datos y utilizando SQLCipher para el encryption de la database. Estoy utilizando la queue serie GCD para todas las operaciones relacionadas con la database y la gestión manual de la memory. A continuación se muestra un fragment de código para mis operaciones relacionadas con la database. Tengo más methods como saveRecordData: que llama a executeOnGCD: para diferentes types de loggings.

 -(void)saveRecordData:(NSArray *)dataObjects{ [self executeOnGCD:^{ std::vector<RecordData> list; for(id object in dataObjects){ RecordData recordDataObject(/*create c++ data object*/) list.push_back(recordDataObject); } DataBaseManager::GetInstance()->saveData(list); }]; } -(void)executeOnGCD:(void (^)())block{ __block UIBackgroundTaskIdentifier task = UIBackgroundTaskInvalid; task = [[UIApplication shanetworkingApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication shanetworkingApplication] endBackgroundTask:task]; task=UIBackgroundTaskInvalid; }]; void (^executionBlock)() = ^(){ @autoreleasepool { block(); [[UIApplication shanetworkingApplication] endBackgroundTask:task]; task=UIBackgroundTaskInvalid; } }; //dataManagerQueue is serial queue. dispatch_async(self.dataManagerQueue, executionBlock); } 

Aquí DataBaseManager es una class C ++ que realiza una inserción de database real. La implementación saveData de DataBaseManager es la siguiente.

 void saveData(std::vector<RecordData> list) { for(RecordData record : list) { sqlite3_stmt * statement = nullptr; if(sqlite3_prepare_v2(m_dbConnection, INSERT_STATEMENT, -1, &statement, NULL) == SQLITE_OK) { //Bind parameters int index = sqlite3_bind_parameter_index(statement, COLUMN1); sqlite3_bind_int(statement, index, value1); index = sqlite3_bind_parameter_index(statement, COLUMN2); sqlite3_bind_int(statement, index, value2); /*Bind other parameters*/ sqlite3_step(statement); } sqlite3_finalize(statement); } } 

Cuando mi aplicación guarda 80k + loggings usando la function saveData, hay una diferencia de asignación de memory entre cuando comenzó la operación y cuando la operación finalizó. Los instrumentos sugieren que todavía hay memory asignada por SQLCipher que no se libera incluso después de los 5 minutos de finalización de la operación. Como se muestra en la image siguiente al comienzo de la operación, la asignación de memory fue de 1.90 mb y, una vez completada, la memory de tareas se networkinguce a 6.6 mb y no a 1.90 mb

introduzca la descripción de la imagen aquí

También una vez completada la operación, la memory se networkinguce muy lentamente y toma alnetworkingedor de 6 minutos para networkingucir la memory de 20 MB a 6.6 MB.

mis preguntas son

1) ¿Por qué la memory no cayó a ~ 1.90mb después de completar la tarea? ¿Esto está relacionado con el uso de objects c ++ en GCD?

2) ¿Por qué tarda ~ 6min en networkingucir la memory de 20 MB a 6.6 MB? ¿GCD libera la memory lentamente?

3) También veo _dispatch_alloc_try_create_heap block asignado por libdispatch.dylb, que tampoco se libera después de la finalización de la operación.

4) ¿Estoy usando el enfoque correcto para bloques nesteds en executeOnGCD: método?

No sé la respuesta exacta a la situación que tienes, pero tengo algunas sugerencias, y fueron más de lo que cabría en un comentario …

Lo que quiere hacer aquí es observar los rastros de stack de los events gratuitos que están sucediendo durante los 6 minutos posteriores a la finalización. Eso debería darle algunas pistas sobre cómo se progtwign las desocupaciones. Parece probable que haya algo de hilo de background haciendo la limpieza. Obtener esos rastreos de stack debería permitirle search en el código dónde se planificó originalmente esa limpieza, y eso debería proporcionar las respuestas que busca.

La estrecha similitud entre las pendientes ascendentes y descendentes de ese gráfico me hace pensar que (conceptualmente) un timer se inicia cuando se usa el object por última vez, y que hay algún mecanismo que los cosecha después de un período de inactividad. Probablemente se implementa registrando los objects con algún logging en el momento malloc, luego actualizando un campo lastUsed en cada uso del object, y luego un process periódico camina en la list y dice, efectivamente, "libera todos los objects que no se han usado por X cantidad de time ". Esto podría existir para proporcionar algún tipo de mecanismo de caching implícito.

No conozco absolutamente nada de esto, pero parece una explicación probable.