Commit Graph
1 Commits
Author SHA1 Message Date
what a2c0c9783e perf: New(值) 对不含引用成分的类型改走浅拷贝
New(值) 的语义是"改副本不影响调用方的原数据", 原来一律走 DeepClone 递归。
但对于不含引用成分的类型, 逐字节拷贝就已经完全独立了, 没必要递归。

在类型描述符里加 needsClone(构建期算一次, 不在热路径):
含指针/切片/map/interface/chan/func/unsafe.Pointer 即为真, 递归包含字段与
数组元素。字符串不算 —— 底层数组不可变, 共享是安全的。

  New(纯值 struct)   145.0ns -> 85.5ns   1.70x
  New(含引用 struct) 304.9ns             不变(深拷贝确实必要)
  New(&ptr)           25.8ns             不变

注意 1.70x 而不是更多: New 还要做类型断言、normalizeInputValue、递归解引用、
类型校验和描述符查找, 省掉的只是深拷贝那一段(约 59ns)。

needsClone 必须在递归之前按 Kind 置位, 否则自引用类型会漏标: 类型图里的环
一定要经过某种间接(指针/切片/map), 先置位才能让递归回来的自引用类型读到
正确的值。测试里专门有一条 cNode{Next *cNode} 守这个。

判错的后果是静默的数据串改 —— 浅拷贝一个含引用的类型, 写入会穿透到调用方
的原数据, 不报错也不 panic。所以测试分两层:
  1. needsClone 判定本身: 14 个用例, 含"引用藏在两层嵌套下"、"藏在数组元素里"、
     自引用、time.Time(内含 *Location)等容易漏判的形态
  2. 隔离语义: 7 个用例, 无论走哪条路都断言原数据未被改写
  3. 与旧实现对拍: 5 种输入 x 5 个观察方法

已验证测试有效: 把 needsClone 强制为 false 后, 6 个隔离用例全部失败, 包括
藏在两层嵌套和数组元素里的引用。
2026-08-31 11:10:49 +08:00