在学习F#时,我偶尔会编写一些算法的变体(具有相同的渐近复杂度)以获得乐趣。但最后,我还想要了解一些我想继续使用或改进的见解。
所以我使用F#interactive和#time
命令。明显的决策标准当然是完成某项任务所需的时间。但我得到的其他信息我怀疑与垃圾收集统计数据有关。但我真的不知道该怎么做。
以下是三种置换算法的一些示例时序:
> let len = 10
> let last _ = // some way of knowing all have been seen (i.e. counting)
> let a = [|1..len|]
> a |> grayPermutations |> Seq.find last |> printfn "%A"
> [|2; 1; 3; 4; 5; 6; 7; 8; 9; 10|]
Real: 00:00:13.323, CPU: 00:00:13.343, GC gen0: 763, gen1: 762, gen2: 1
> a |> permutations |> Seq.find last |> printfn "%A"
> [|10; 9; 8; 7; 6; 5; 4; 3; 2; 1|]
Real: 00:00:00.631, CPU: 00:00:00.625, GC gen0: 138, gen1: 138, gen2: 0
> a |> findPermutation last |> printfn "%A"
> [|10; 1; 2; 3; 4; 5; 6; 7; 8; 9|]
Real: 00:00:04.400, CPU: 00:00:04.390, GC gen0: 385, gen1: 385, gen2: 0
获胜者很清楚,但是时间过后告诉我的是什么?可以(或应该)我尝试优化这个 - 给定我知道它意味着什么?
答案 0 :(得分:3)
#time
指令的输出输出实时,cpu时间和垃圾收集信息,您可以在其中查看所有三代managed heap中垃圾收集操作的数量
第0代。这是最年轻的一代,包含短期对象。短期对象的一个例子是临时的 变量。垃圾收集最常发生在此 代。新分配的对象形成新一代对象 并且是隐式生成0集合,除非它们很大 对象,在这种情况下,它们在一个大的对象堆上 第2代收藏。大多数物体都被回收用于垃圾 在第0代收集并且不能存活到下一代。
第1代。这一代包含短期对象,并作为短期对象和长期对象之间的缓冲区。
第2代。这一代包含长寿命的对象。长期存在的对象的示例是服务器应用程序中的对象 包含在持续时间内生效的静态数据 过程
另一方面,严格按执行时间评估算法是有缺陷的,因为你可以有一个在O(n)时间运行的方法和另一个在O(n2)时间运行的方法,但它们之间的差异仅表现为大投入。