gpt4 book ai didi

c++ - GCD-> block ->C++->SQLCipher : Sqlite3MemMalloc memory does not release after task completion

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:36:23 25 4
gpt4 key购买 nike

我正在研究数据库应用程序并使用 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

enter image description here

此外,一旦操作完成,内存减少非常缓慢,大约需要 6 分钟才能将内存从 20mb 减少到 6.6mb。

我的问题是

1) 为什么任务完成后内存没有下降到 ~1.90mb?这与在 GCD 中使用 C++ 对象有关吗?

2) 为什么将内存从 20mb 减少到 6.6mb 需要大约 6 分钟? GCD释放内存慢吗?

3) 我还看到 _dispatch_alloc_try_create_heap block 由 libdispatch.dylb 分配,在操作完成后也没有释放。

4) 我是否在 executeOnGCD: 方法中对嵌套 block 使用了正确的方法?

最佳答案

我不知道你所遇到的情况的确切答案,但我有一些建议,它们超出了评论的范围......

您在这里要做的是查看完成后 6 分钟内发生的免费事件的堆栈跟踪。这应该会给您一些关于如何安排重新分配的线索。似乎有一些后台线程在进行清理。获取这些堆栈跟踪应该允许您搜索代码以查找最初安排清理的位置,并且应该提供您寻求的答案。

该图的向上斜率和向下斜率之间的密切相似性让认为(概念上)计时器在对象最后一次使用时启动,并且有某种机制可以在一段时间后收获它们不活动的时期。这可能是通过在 malloc 时间向某个注册表注册对象,然后在每次使用对象时更新 lastUsed 字段来实现的,然后一个周期性的过程遍历列表并有效地说,“释放所有X 时间未使用的对象。”这可能存在以提供某种隐式缓存机制。

我不确定这些,但这似乎是一个可能的解释。

关于c++ - GCD-> block ->C++->SQLCipher : Sqlite3MemMalloc memory does not release after task completion,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30122981/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com