在 iOS 上使用 MongoDB Realms 时出现 KMM 内存泄漏(RAM + 磁盘)问题

KMM Memory Leak (RAM + Disk) issue when using MongoDB Realms on iOS

提问人:rowjammer 提问时间:9/21/2023 最后编辑:rowjammer 更新时间:10/26/2023 访问量:65

问:

我过去一直在使用 Java Realm 开发 Android 应用程序,最近我将其迁移到 Kotlin Multiplatform,以使其与 iOS 兼容。经过测试,似乎通过在 iOS 环境中运行它,我的内存因泄漏而饱和,这影响了 RAM 和磁盘(它会在几周的测试中完全填满,全部为 64Gb)。因此,我制作了一个非常简单的降级版本,展示了它到底失败了什么。简而言之,通过调用 realm.open 和 realm.close 方法,我泄漏了内存(根据 Xcode 上的内存图,realm_scheduler 实例,但任何与领域相关的内容似乎都会在其中创建过多的实例)。

Xcode 内存图示

简而言之,我要在 iOS 上运行的 Swift 代码只执行这个,它会创建一个计时器,每 .1 秒从 RealmLeaker 的实例调用 leak():

    var leaker = RealmLeaker()
    // Code skipped here for readability
        NavigationView {
            Text("A")
        }
        .onAppear() {
            var timer1 = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timerI in
                // Leaking
                leaker.leak()
            }
        }

在 KMM 方面,这里是 RealmLeaker 类:

class RealmLeaker {
    fun leak() {
        val config = RealmConfiguration.Builder(setOf(TestClass::class))
            .build()

        // This should simply open, then close the realm. Note that if you comment everything below this, there is no leak.
        val realm: Realm = Realm.open(config)
        realm.close()
    }
}

为了获得更多上下文,这是我在 Kotlin 端使用的“TestClass”:

// This class isn't really useful. Only there to showcase the leak, its properties are outside the scope of the problem.
class TestClass : RealmObject{
    @PrimaryKey
    var _id : String = "0"

    var value : Boolean = false
    var key : String = "test"
}

从逻辑上讲,这段代码应该只是打开和关闭 Realm,不会丢失内存,但它会填满我的 RAM 和磁盘内存。

下面是一个重现错误的存储库: GitHub - ALXgba/realmKMMIssue:在 iOS 环境中运行时,在 KMM 项目中使用 Kotlin API 时发生内存泄漏。 1

我确实在 MongoDB Realms GitHub 页面上打开了一个问题,但由于他们还没有回答,我希望我错过的内容可能是基本的,并且我可能会在我的代码中修复它,因为我希望快速规避这个问题。这是问题页面: https://github.com/realm/realm-kotlin/issues/1501

虽然使用 Xcode 调试图时问题似乎并不那么可怕,但如前所述,它没有清楚地表明应用程序在磁盘上的大小也在无限增长。这意味着如果用户想要频繁使用这个应用程序,他们需要定期卸载并重新安装它,并在此过程中擦除 Realm。此外,使用的 RAM 似乎以很小的速度增长,但我在我的实际应用程序(不是测试应用程序)中观察到它的增长速度足够快,以至于在一个小时左右后崩溃,因为整个 RAM 被堵塞了。

iOS Swift 领域 kotlin-multiplatform kotlin-native

评论

0赞 rowjammer 9/21/2023
@MaziarSaadatfar谢谢你帮助我!我没有在项目的 swift 方面声明任何类,我也不明白如何在 Kotlin 中声明结构。我对 Kotlin 和 Swift 都很陌生,所以我可能会遗漏一些东西。你说的是命名约定吗?
0赞 Jay 9/23/2023
问题中的代码有点不完整,因为根据 vars 等的实例化方式和位置,结果可能会有所不同。该问题指出它填满了您的磁盘内存。具体用什么?Realm 写入一个名为 default.realm 的文件。如果只打开和关闭一次领域,该文件包含哪些内容?如果运行应用程序(反复打开和关闭它),该文件包含哪些内容?您可以使用 Realm Studio 应用程序检查文件。请用具体填充磁盘的内容来更新问题?

答:

0赞 rowjammer 10/26/2023 #1

对于任何尝试此问题的人:

Realms 存在一个内部问题,简而言之,它涉及 iOS 等价于 GC 的循环依赖关系。该问题已通过以下拉取请求关闭: https://github.com/realm/realm-kotlin/pull/1530 它尚未在实际版本中推送,但使用与其当前分支链接的 1.11.2-SNAPSHOT 可以解决问题。(https://github.com/realm/realm-kotlin/tree/releases;有关详细信息,请参阅 README.md 中的“使用快照”。