【发布时间】:2020-01-10 06:33:00
【问题描述】:
我发现在 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":$0])})
try? realm.write {
realm.add(leakTestList)
}
}
leakTest()返回后,得到如下内存配置文件:
LeakTestList 已经消失,但所有项目都保留在内存中。当我尝试编写大量列表项甚至分成多个足够短的列表时,这会导致内存不足。这是 Realm 的错误还是我可以做些什么来解决这个问题?
【问题讨论】:
-
不是反对者,但我不确定我是否在关注这个问题。在内存中创建了一堆 Realm 对象,并且假设存在内存泄漏?他们还会在哪里? Realm 对象被延迟加载,这不是代码。
-
@Jay 创建了一堆 Realm 对象,并将其添加到另一个 Realm 对象的 List 中。当函数返回时,不再有对对象的引用。即使包含列表的对象已经被释放,列表项也不会被释放。假设我只有 2GB 的 RAM,并且想编写一个占用 3GB RAM 的领域对象列表。一轮写完是不可能的,但即使我将列表分成更小的部分,仍然是不可能的,因为这些项目永远不会释放。
-
我使用的是写入磁盘文件的默认领域,而不是纯内存领域。我最近发现我将测试函数放在 viewDidLoad 中,并且列表项领域对象在整个 viewDidLoad 中保持分配,但在 viewDidAppear 中被解除分配。我只是想知道未引用的领域对象何时会完全释放,因为我必须将它们中的很多写入磁盘。
-
我们已经被这个问题抓住了好几次,所以我想提到该代码写入的文件的大小比它需要的大得多。一方面,使用单个写入事务来写入一堆数据通常比使用一堆添加较小数据的写入事务要好。另一方面,单次写入将创建一个 更大的文件,但速度更快。请参阅@bdash 对this question 的回复。
-
哦 - 还有一个后续问题;您说当函数返回时,不再有对对象的引用,然后说列表项没有被释放。我运行了您的代码,当泄漏测试函数结束时,没有任何对象-泄漏测试列表和泄漏测试项目仍在内存中。您是说没有对这些对象的引用,但 函数完成后它们仍在内存中?
标签: ios swift memory-leaks realm realm-list