我最近遇到了意外的代码优化,想检查一下我对所观察到的内容的解释是否正确。以下是该情况的一个非常简化的示例:
let demo =
let swap fst snd i =
if i = fst then snd else
if i = snd then fst else
i
[ for i in 1 .. 10000 -> swap 1 i i ]
let demo2 =
let swap (fst: int) snd i =
if i = fst then snd else
if i = snd then fst else
i
[ for i in 1 .. 10000 -> swap 1 i i ]
两个代码块之间的唯一区别是,在第二种情况下,我将 swap 的参数显式声明为整数。然而,当我使用#time 在 fsi 中运行 2 个片段时,我得到:
案例 1 真实:00:00:00.011,CPU:00:00:00.000,GC gen0:0,gen1:0,gen2:0
案例 2 真实:00:00:00.004,CPU:00:00:00.015,GC gen0 :0,第一代:0,第二代:0
即第二个片段的运行速度是第一个片段的 3 倍。这里的绝对性能差异显然不是问题,但是如果我大量使用交换功能,它就会堆积起来。
我的假设是性能下降的原因是,在第一种情况下,swap 是通用的并且“需要相等”,并检查 int 是否支持它,而第二种情况不需要检查任何东西。这是发生这种情况的原因,还是我错过了其他东西?更一般地说,我是否应该将自动泛化视为一把双刃剑,也就是说,一个很棒的功能可能会对性能产生意想不到的影响?