GCD->blocks->C++->SQLCipher: 任务完成后Sqlite3MemMalloc内存没有被释放

3

我正在开发数据库应用程序,并使用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:方法中使用嵌套块的方法正确吗?
1个回答

0

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

你需要做的是查看完成后6分钟内发生的免费事件的堆栈跟踪。这应该能够给你一些线索,以了解如何安排释放操作。似乎有一些后台线程在进行清理。获取这些堆栈跟踪应该允许你搜索代码,找到最初安排清理操作的位置,这应该提供你所需的答案。

图表上升和下降斜率之间的相似性使我认为(概念上),当对象最后使用时启动计时器,并且有一些机制在一段时间内收割它们。这可能是通过在malloc时将对象注册到某个注册表中实现的,然后在每次使用对象时更新lastUsed字段,然后定期处理程序遍历列表并说:“释放所有X时间内未使用的对象。” 这可能存在以提供某种隐式缓存机制。

我不确定这些内容,但它似乎是一个合理的解释。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接