3

我需要在繁重的数值模拟中使用 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
4

1 回答 1

8

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

  1. 它是一个值类型,所以不需要堆分配
  2. 它仅支持将值类型作为元素,因此您可以创建一个option<string>,但不能创建一个Nullable<string>. 对于您的用例,这似乎是一个不重要的因素。
  3. 它具有运行时支持,因此将没有值的可空值装箱会导致空引用,否则这是不可能的

请记住,您的基准测试所做的工作很少,因此结果可能与您在实际工作负载下看到的结果不同。如果可能,请尝试根据您的实际情况使用更有意义的基准。

附带说明一下,如果您#time在 F# 中使用该指令而不是使用Stopwatch.

于 2013-05-20T16:02:48.893 回答