是否存在此功能?像Java HotSpot在服务器模式下运行,但是用于.Net应用程序。
修改 更多信息。我有一个小应用程序(用F#编写),我有很多小函数。像这样:
let printable b =
if b >= ' 'B && b <= '~'B
then b else '.'B
我已经意识到性能很差,在分析后我发现每个这样的功能都被称为数百万次。我做了inline
并且提升了性能(5次以上,可能更多)。
好的,好的。现在表现很好。但为什么框架没有呢?它有足够的关于我的代码的信息以及调用函数的频率。为什么它没有内联一个被称为1M次的函数?
EDIT2: 用于测量内联函数差异的样本测试:
open System
let printableByte b =
if b >= ' 'B && b <= '~'B
then b else '.'B
let foo (arr : byte[]) =
for i in 0..arr.Length-1 do
arr.[i] <- printableByte (arr.[i])
arr.Length / 1000
let main() =
let sum = ref 0
let arr = Array.create 1000000 0uy
let stopWatch = System.Diagnostics.Stopwatch()
stopWatch.Start()
for x in 0..5000 do
sum := !sum + (foo arr)
stopWatch.Stop()
printfn "%d" !sum
printfn "total time = %A" stopWatch.ElapsedMilliseconds
()
main()
当printableByte
未内联时为19.5秒,内联时为13.6秒。
EDIT3: 只有在为x86目标编译并在x64主机上运行时,才能查看此时间差。如果编译为“anycpu”或x64,则没有时间差异。
因此,“小功能”和优化没有任何问题。
答案 0 :(得分:4)
是的,CLR执行一些运行时优化,正如blog所示。 请注意,根据这篇文章,虚拟方法不内联。
这两种方法都没有内联:
- 递归方法
- 虚拟方法(即使密封接收器变量的静态类型)
您的代码中调用了printable
函数怎么样?如果F#编译器将它包装在一个闭包中,它经常会这样做,即使在你最初可能没想到它的情况下,那么你将陷入“虚方法”的情况。
答案 1 :(得分:1)
请注意,在FSI中测试此代码与在Release
模式下编译项目不一样。
我的高度非科学测试表明,如果将Debug
添加到inline
,则printableByte
的效果会更好。
但是,在inline
模式下添加Release
时,程序实际上执行更糟比没有它时更糟糕。我确信F#编译器团队或一些反汇编可以告诉你为什么......
根据我使用F#的经验,您很少必须手动应用内联优化。只需确保在Release
中编译!
编辑:啊哈,是的!一定要在“任何CPU”模式下编译,除非你有特殊的理由不这样做(通常我的理由是必须与F#的x86 COM库进行互操作)
答案 2 :(得分:0)
是的,.net框架优化了它运行的平台的代码。它需要考虑许多因素。但是有一些事情是不会做的。例如,如果它们可用,我不相信它会使用SIMD指令。但它确实在优化方面做得很好。