为什么在 F# 中使用引用大值的字段创建记录如此缓慢?

nas*_*sev 3 memory performance f# reference record

在下面作为 .fsx 脚本执行的代码中,最后一行大约需要 30 秒才能完成。我假设由于记录是引用类型,最后一行只创建带有引用(不可变)大值的字段的记录,因此它应该非常快。为什么它很慢,我该如何解决?

type BigType = { Big: Set<int> }
type CollectionType = { BigVal: BigType; SmallVal: int }

let b = { Big = set [ 0 .. 999999 ] }
let mySet = set [ 0 .. 50 ]

#time

mySet |> Set.map (fun x -> { BigVal = b; SmallVal = x })
Run Code Online (Sandbox Code Playgroud)

谢谢你。

Jac*_*son 5

这里要注意的一件事是,您定义字段的顺序type CollectionType = { BigVal: BigType; SmallVal: int }会有所不同。如果你试试:

type BigType = { Big: Set<int> }
type CollectionType = { SmallVal: int; BigVal: BigType; }
let b = { Big = set [ 0 .. 999999 ] }
let mySet = set [ 0 .. 50 ]
#time
mySet |> Set.map (fun x -> { BigVal = b; SmallVal = x })
Run Code Online (Sandbox Code Playgroud)

相反,所用时间从 Real: 00:00:34.385 到 Real: 00:00:00.002。

NB:我最初担心这种行为不能被依赖并且可能会在没有警告的情况下改变;然而,由于 nasosev 发现此行为在F# 语言规范中有所描述,请参阅文档 4.1 版的第 8.15.3 节。