内存模型演进
源:Kotlin/Native Memory Model Evolution
Kotlin/Native 的内存模型经历了重大演进,从严格的对象不可变模型转向更现代的自动内存管理。了解这段历史有助于理解当前设计。
传统内存模型 (Legacy MM)
不可变性与冻结
传统模型基于严格的线程隔离:
kotlin
// 传统模型
class Counter {
var value = 0
fun increment() {
value++
}
}
fun oldThreading() {
val counter = Counter()
counter.increment() // OK: 在主线程
// 跨线程共享前必须冻结
counter.freeze()
Worker.start().execute(TransferMode.SAFE, { counter }) {
// ❌ InvalidMutabilityException
// it.increment() // 冻结后无法修改
// ✅ 只能读取
println(it.value)
}
}Worker 线程模型
kotlin
// 传统 Worker API
val worker = Worker.start()
// 传递数据到 Worker
val future = worker.execute(TransferMode.SAFE, { "Data" }) { data ->
// Worker 线程中执行
processData(data)
}
// 获取结果
val result = future.result
// 清理
worker.requestTermination().result局限性
- 开发复杂度高 - 需要手动管理冻结
- 共享困难 - 可变对象无法跨线程共享
- 性能开销 - 频繁的对象拷贝
- 与 JVM 差异大 - 难以编写跨平台代码
新内存模型 (New MM)
自动内存管理
新模型(Kotlin 1.7.20 起默认)移除了冻结限制:
kotlin
// 新模型
class Counter {
@Volatile
var value = 0
fun increment() {
atomicValue.incrementAndGet()
}
}
fun newThreading() {
val counter = Counter()
// ✅ 直接跨线程共享,无需冻结
repeat(5) {
Worker.start().execute(TransferMode.SAFE, { counter }) {
it.increment()
}
}
// 需要手动同步
Thread.sleep(100)
println(counter.value) // 5
}GC 改进
kotlin
@OptIn(ExperimentalStdlibApi::class)
import kotlin.native.runtime.GC
// 新 GC 控制
GC.collect() // 触发 GC
GC.schedule() // 安排 GC
// 获取 GC 信息
val info = GC.lastGCInfo
println("GC pause: ${info?.pauseTimeNs}ns")迁移指南
迁移步骤
kotlin
class DataProcessor {
private val cache = mutableMapOf<String, String>()
init {
freeze() // 冻结整个对象
}
fun process(key: String): String? {
// ❌ 无法修改 cache
return cache[key]
}
}kotlin
class DataProcessor {
// ✅ 使用线程安全的集合
private val cache = ConcurrentMutableMap<String, String>()
// 或使用锁
private val lock = Any()
private val cacheWithLock = mutableMapOf<String, String>()
fun process(key: String): String? {
return synchronized(lock) {
cacheWithLock[key]
}
}
}删除 freeze 调用
bash
# 查找所有 freeze 调用
grep -r "\.freeze()" src/
# 评估是否需要替代方案
# - 不需要跨线程 → 删除
# - 需要线程安全 → 添加同步使用 @OptIn 标注
kotlin
// 如果必须保留 freeze(临时)
@OptIn(FreezingIsDeprecated::class)
fun legacyCode() {
val obj = MyObject()
obj.freeze()
}性能对比
对象创建
| 场景 | Legacy MM | New MM | 提升 |
|---|---|---|---|
| 简单对象创建 | 100ns | 80ns | 1.25x |
| 跨线程传递 | 300ns (拷贝) | 50ns (直接) | 6x |
| 大对象共享 | 5000ns | 100ns | 50x |
GC 暂停时间
| 堆大小 | Legacy STW | New MM | 改善 |
|---|---|---|---|
| 10MB | 5ms | 2ms | 2.5x |
| 100MB | 50ms | 8ms | 6.25x |
| 1GB | 500ms | 30ms | 16.7x |
新内存模型带来了更符合直觉的编程体验,同时保持了出色的性能。迁移工作量不大,收益显著。