RealmSwift 列表项内存泄漏问题

RealmSwift List items memory leak problem

我发现在 iOS 中向 Realm 写入大量数据会导致内存不足和崩溃。经过几天的排查,我发现 Realm 并没有释放一个 List 中不用的对象。我运行下面的例子:

class LeakTestList : Object{
    var items = List<LeakTestItem>()
}

class LeakTestItem : Object{
    @objc dynamic var data = 0
}


func leakTest()
{
    guard let realm = try? Realm() else
    {
        return
    }
    let leakTestList = LeakTestList()
    leakTestList.items.append(objectsIn: (0..<10000).map{LeakTestItem(value: ["data":[=10=]])})
    try? realm.write {
        realm.add(leakTestList)
    }
}

leakTest()return之后,我得到了以下内存配置文件:

LeakTestList 已经消失,但所有项目都保留在内存中。当我试图写很多列表项甚至分成多个足够短的列表时,这会导致内存不足。这是 Realm 的错误还是我可以做些什么来解决这个问题?

我们发现在领域中建立对象,然后以较小的块附加到该对象似乎不仅有助于解决内存中的问题,而且还能显着减小文件大小。

我们的项目必须读取和处理 50Gb 以上的文件,我们发现一次写入大约 1000 个对象似乎是速度、文件大小和内存之间的平衡点。您的里程数可能会有所不同。

我重构了您的代码并添加了几个 for 循环以显示正在发生的事情,但试试这个,看看相比之下内存占用是否更好。

这会以较小的块写入总共 10 个项目,正如我在评论中提到的那样,这会减小整体文件大小。对于您的示例,外部循环为 40,内部循环为 1000。

let leakTestList = LeakTestList()

try? realm.write {
    realm.add(leakTestList)
}

var index = 0
for _ in 0..<2 {
    var myItems = [LeakTestItem]()
    for _ in 0..<5 {
        let item = LeakTestItem( value: ["data": index] )
        myItems.append(item)
        index += 1
    }

    try? realm.write {
        leakTestList.items.append(objectsIn: myItems)
    }
}

参考@Jay 的回答,我可以从内存监视器中删除领域对象的内存占用,但内存使用保持不变,直到 viewDidLoad() 结束。经过更多挖掘后,我发现我错过的关键想法是将所有内容都包装在 autoreleasepool 中。参考这篇文章:https://realm.io/docs/cookbook/swift/object-to-background/

func leakTest()
{
    autoreleasepool {
        guard let realm = try? Realm() else
        {
            return
        }

        let leakTestList = LeakTestList()

        try? realm.write {
            realm.add(leakTestList)
        }

        try? realm.write {
            leakTestList.items.append(objectsIn: (0..<10000).map{LeakTestItem(value: ["data":[=10=]])})
        }
    }
}