一尘不染

超出预期的Realm文件大小

swift

这个问题是关于使用两种不同的方法将对象插入领域的。我注意到第一种方法要快得多,但是与第二种方法相比,尺寸结果是巨大的。两种方法之间的差异在于将写事务移到for循环的内部还是外部。

// Create realm file
let realm = try! Realm(fileURL: banco_url!)

当我添加这样的对象时,Realm文件将增长到75.5MB:

try! realm.write {
    for i in 1...40000 {
        let new_realm_obj = realm_obj(value: ["id" : incrementID(),
                                              "a": "123",
                                              "b": 12.12,
                                              "c": 66,
                                              "d": 13.13,
                                              "e": 0.6,
                                              "f": "01100110",
                                              "g": DateTime,
                                              "h": 3])

        realm.add(new_realm_obj)
        print("🔹 \(i) Added")
    }
}

当我添加这样的对象时,Realm文件仅增长到5.5MB:

for i in 1...40000 {
    let new_realm_obj = realm_obj(value: ["id" : incrementID(),
                                          "a": "123",
                                          "b": 12.12,
                                          "c": 66,
                                          "d": 13.13,
                                          "e": 0.6,
                                          "f": "01100110",
                                          "g": DateTime,
                                          "h": 3])
    try! realm.write {
        realm.add(new_realm_obj)
        print("🔹 \(i) Added")
    }
}

我的班级要添加到领域文件

class realm_obj: Object {
    dynamic var id = Int()
    dynamic var a = ""
    dynamic var b = 0.0
    dynamic var c = Int8()
    dynamic var d = 0.0
    dynamic var e = 0.0
    dynamic var f = ""
    dynamic var g = Date()
    dynamic var h = Int8()
}

自动递增功能

func incrementID() -> Int {
    let realm = try! Realm(fileURL: banco_url!)
    return (realm.objects(realm_obj.self).max(ofProperty: "id") as Int? ?? 0) + 1
}

有没有更好或正确的方法来做到这一点?在这种情况下,为什么会得到如此不同的文件大小?


阅读 348

收藏
2020-07-07

共1个答案

一尘不染

在单个事务中添加所有对象时,较大的文件大小是由于Realm的事务日志子系统与Realm的大型Blob内存分配算法之间不幸的相互作用所致。Realm的内存布局算法要求文件大小至少是Realm文件中存储的最大单个Blob大小的8倍。汇总单个事务期间所做的修改的事务日志条目将作为blob存储在Realm文件中。

在一个事务中添加40,000个对象时,最终只有一个事务日志条目,大小约为5MB。这意味着文件的大小必须至少为40MB才能存储。(我不太确定它最终会变成两倍大小的结果。可能是斑点的大小沿线的某个部分四舍五入为2的幂…)

当您在40,000个事务中添加一个对象时,仅此一次它只有100个字节左右的大小时,仍然会得到一个事务日志条目。发生这种情况的原因是,当Realm提交事务时,它先尝试回收未使用的事务日志条目,然后再为新条目分配空间。由于Realm文件未在其他位置打开,因此在执行每个新的提交时都可以回收先前的条目。

realm / realm-core#2343跟踪如何改进Realm存储事务日志条目的方式,以避免您看到的大量过度分配。

现在,我的建议是拆分两种方法之间的差异,并为每个写入事务添加对象组。这将通过增加提交次数来降低性能,但是会通过减小创建的最大事务日志条目的大小来减少内存布局算法的影响。通过快速测试,每提交2,000个对象将产生大约4MB的文件大小,而比在单独的写入事务中添加每个对象要快得多。

2020-07-07