Function 使用F优化记录中的函数值访问#

Function 使用F优化记录中的函数值访问#,function,optimization,f#,record,Function,Optimization,F#,Record,F#不够聪明,无法优化以下代码,有什么原因吗快速=880和慢速=8090 type Data = { fn: int * int -> int } let fn (x, y) = x + y let data = { fn = fn } let mutable a = 0 let s = System.Diagnostics.Stopwatch() s.Start() for i in 0 .. 1000000000 do a <- fn(i, i) printfn "fas

F#不够聪明,无法优化以下代码,有什么原因吗<代码>快速=880和
慢速=8090

type Data = { fn: int * int -> int }
let fn (x, y) = x + y
let data = { fn = fn }

let mutable a = 0
let s = System.Diagnostics.Stopwatch()

s.Start()
for i in 0 .. 1000000000 do
  a <- fn(i, i)
printfn "fast = %d" s.ElapsedMilliseconds

s.Restart()
for i in 0 .. 1000000000 do
  a <- data.fn(i, i)
printfn "slow = %d" s.ElapsedMilliseconds
type Data={fn:int*int->int}
设fn(x,y)=x+y
让数据={fn=fn}
设可变a=0
设s=System.Diagnostics.Stopwatch()
s、 开始()
因为我在0。。10亿美元

a快速路径是内联的
fn
,而慢速路径是进行函数调用

注意,您甚至不需要该记录,只需执行以下操作即可:

let fn' = fn
for i in 0 .. 1000000000 do
  a <- fn'(i, i)
printfn "slow = %d" s.ElapsedMilliseconds
设fn'=fn
因为我在0。。10亿美元
A.
F#不够聪明,无法优化以下代码,有什么原因吗

如果F#编译器能够优化这种情况,我会感到惊讶。最后,
fn
是一个记录字段,用于保存数据,而不是执行函数

即使在非静态成员上,编译器也不能内联它们,因为这些成员受不断变化的环境的限制。通过声明
let
绑定,您可以利用静态环境的优势,并且编译器可以在一些简单的情况下内联

实际上,在本例中,
fn
函数是内联的(添加
inline
不会改变运行时间)。缓慢的例子是你为手头有一个更强大的构造所付出的代价

每当您必须创建函数记录时,请记住接口和对象表达式是更好的选择(开销越小,智能感知越好):


因此,基于接口的方法比基于记录的方法快3倍,比内联方法慢3倍。

对不起,这并不能真正回答您的问题,即编译器为什么不能优化它。+1不过,这是一个很好的问题说明。我认为您的问题不太正确。正确的问题是为什么安装程序不优化它,而不是为什么它不能优化它。
type Data2 =
    abstract fn : int * int -> int

let data2 = 
    { new Data2 with
        member __.fn (x, y) = fn (x, y) }

s.Restart()
for i in 0 .. 1000000000 do
  a <- data2.fn(i, i)
printfn "a bit slow = %d" s.ElapsedMilliseconds
fast = 614
slow = 7498
a bit slow = 2765