我正在开发数据库应用程序,并使用SQLCipher进行数据库加密。 我正在使用GCD串行队列处理所有与数据库有关的操作和手动内存管理。 以下是我数据库相关操作的代码片段。 我还有更多类似于saveRecordData:
的方法,它们为不同类型的记录调用executeOnGCD:
。
-(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 sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:task];
task=UIBackgroundTaskInvalid;
}];
void (^executionBlock)() = ^(){
@autoreleasepool {
block();
[[UIApplication sharedApplication] endBackgroundTask:task];
task=UIBackgroundTaskInvalid;
}
};
//dataManagerQueue is serial queue.
dispatch_async(self.dataManagerQueue, executionBlock);
}
这里的DataBaseManager是一个C++类,用于执行实际的数据库插入操作。DataBaseManager的saveData实现如下:
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);
}
}
当我的应用程序使用saveData函数保存80k+条记录时,操作开始和结束时的内存分配存在差异。仪器显示SQLCipher仍然分配了内存,即使在5分钟的操作完成后也没有释放。如下图所示,在操作开始时,内存分配为1.90mb,完成任务后内存减少到6.6mb而不是1.90mb。
此外,一旦操作完成,内存减少得非常缓慢,需要约6分钟才能将内存从20mb减少到6.6mb。
我的问题是:
1)为什么任务完成后内存没有降至1.90mb?这与在GCD中使用c++对象有关吗?
2)为什么需要约6分钟才能将内存从20mb减少到6.6mb?GCD释放内存很慢吗?
3)我还看到libdispatch.dylb分配的_dispatch_alloc_try_create_heap块,在操作完成后也没有被释放。
4)我在executeOnGCD:方法中使用嵌套块的方法正确吗?