我正在编写一个64位F#解决方案,分析表明在JIT_TailCall中花费了出乎意料的大量时间...实际上它占据了运行时间的80%左右。这与其邪恶的表兄JIT_TailCallHelperStub_ReturnAddress一起出现。
我肯定已经追踪到问题源头,即在跨越程序集边界时传递结构类型(自定义值类型)的方法或属性调用。我确定这一点,因为如果我绕过方法调用并直接将我的结构赋值给该方法使用的属性,则性能会神奇地提高4-5倍的运行时间!
调用程序集正在使用F# 3.1,因为它正在使用最新稳定版本的FSharp.Compiler.Services进行动态编译。
被调用的程序集正在使用F# 4.0 / .NET 4.6(VS 2015)。
更新:
我试图做的事情的简化是从动态生成的程序集中将自定义结构值分配给数组中的位置...
当调用以下内容时,运行时速度很快,不会生成多余的尾调用:
1.公开类型中私有数组的属性
但是,由于调用以下内容而生成多余的尾调用,导致运行时变慢:
1.公开数组的索引器属性(Item)
2.作为数组setter的成员方法
我需要调用成员方法的原因是我需要在将项插入数组之前执行一些检查。
实用:
除了理解问题的根源外,我想知道F# 4.0是否会解决这个问题,从而暗示即将发布的FSharp.Compiler.Services也会解决这个问题。考虑到更新的FSharp.Compiler.Services相对即将推出,最好等待它的到来。
我肯定已经追踪到问题源头,即在跨越程序集边界时传递结构类型(自定义值类型)的方法或属性调用。我确定这一点,因为如果我绕过方法调用并直接将我的结构赋值给该方法使用的属性,则性能会神奇地提高4-5倍的运行时间!
调用程序集正在使用F# 3.1,因为它正在使用最新稳定版本的FSharp.Compiler.Services进行动态编译。
被调用的程序集正在使用F# 4.0 / .NET 4.6(VS 2015)。
更新:
我试图做的事情的简化是从动态生成的程序集中将自定义结构值分配给数组中的位置...
当调用以下内容时,运行时速度很快,不会生成多余的尾调用:
1.公开类型中私有数组的属性
但是,由于调用以下内容而生成多余的尾调用,导致运行时变慢:
1.公开数组的索引器属性(Item)
2.作为数组setter的成员方法
我需要调用成员方法的原因是我需要在将项插入数组之前执行一些检查。
实用:
除了理解问题的根源外,我想知道F# 4.0是否会解决这个问题,从而暗示即将发布的FSharp.Compiler.Services也会解决这个问题。考虑到更新的FSharp.Compiler.Services相对即将推出,最好等待它的到来。
JIT_TailCall
生成30%的负载,并且为JIT_TailCallHelperStub_ReturnAddress
生成15%的负载。这些函数针对方法变量和类字段进行封闭。当我关闭尾调用生成时,我的性能确切增加了45%。感谢建议将其关闭。开始将递归重写为循环... - V.B.