使用F#的选项类型基准

时间:2013-05-20 15:32:03

标签: f# null benchmarking option

我需要在繁重的数值模拟中使用Some / None选项。以下微基准测试为我提供了Fast = 485Slow = 5890

我不喜欢null,即使我喜欢它们,我也不能使用null,因为The type 'float' does not have 'null' as a proper value

理想情况下,会有一个编译器选项将Some / None编译为value / null,因此不会有运行时惩罚。那可能吗?或者我如何使Some / None有效?

let s = System.Diagnostics.Stopwatch()

s.Start()
for h in 0 .. 1000 do
  Array.init 100000 (fun i -> (float i + 1.)) |> ignore
printfn "Fast = %d" s.ElapsedMilliseconds

s.Restart()
for h in 0 .. 1000 do
  Array.init 100000 (fun i -> Some (float i + 1.)) |> ignore
printfn "Slow = %d" s.ElapsedMilliseconds

1 个答案:

答案 0 :(得分:8)

None实际上已经表示为null。但由于option<_>是引用类型(null必须是.NET类型系统中的有效值),因此创建Some实例必然需要堆分配。一种替代方法是使用.NET System.Nullable<_>类型,类似于option<_>,除了:

  1. 它是一个值类型,因此不需要堆分配
  2. 它仅支持将值类型作为元素,因此您可以创建option<string>,但不能创建Nullable<string>。对于您的用例,这似乎是一个不重要的因素。
  3. 它具有运行时支持,因此装入一个没有值的可空值会导致空引用,否则这是不可能的
  4. 请记住,您的基准测试所做的工作很少,因此结果可能不是您在实际工作负载中看到的典型结果。如果可能的话,尝试根据您的实际情况使用更有意义的基准。

    作为旁注,如果您在F#中使用#time指令而不是打扰Stopwatch,则可以获得更有意义的诊断(包括垃圾收集统计)。