C# / F#性能比较

63

是否有关于C#和F#性能比较的网站可以展示新的F#语言的适当用法?

3个回答

62

自然的F#代码(例如函数式/不可变)比自然的(命令式/可变面向对象)C#代码慢。尽管如此,这种F#代码通常比通常的C#代码更短。显然,这是一种权衡。

另一方面,大多数情况下,您可以实现与C#代码相等的F#代码性能。这通常需要以命令式或可变的面向对象方式编码,对性能进行分析并消除瓶颈。您可以使用与C#相同的工具,例如.Net反射器和分析器。

话虽如此,了解一些在F#中降低性能的高生产力构造还是很有必要的。根据我的经验,我看到以下情况:

  • 引用(与类实例变量相比),只在执行数十亿次的代码中

  • F#比较(<=)与System.Collections.Generic.Comparer相比,在二进制搜索或排序中,例如

  • 尾调用--仅适用于编译器或.Net运行时无法优化的特定情况。如评论中所述,取决于.Net运行时。

  • F#序列的速度比LINQ慢两倍。这是由于引用和F#库中使用的函数来实现seq<_>的翻译。这很容易解决,您可以用具有相同签名并使用Linq、PLinq或DryadLinq的Seq模块替换它。

  • Tuples,F#元组是在堆上排序的类。在某些情况下,例如int*int元组,使用结构体可能更划算。

  • 分配,值得记住的是闭包是一个类,使用new运算符创建,它记住了访问的变量。将闭包"提起来"或用一个显式接受访问的变量作为参数的函数替换它可能是值得的。

  • 尝试使用inline来改善性能,特别是对于泛型代码。

我的经验是首先用F#编码,然后仅针对需要优化的部分进行优化。在某些情况下,编写缓慢的函数可能比尝试调整F#更加容易,但从程序员效率的角度来看,从F#开始/原型制作,然后进行性能分析、反汇编和优化是有意义的。

总的来说,由于程序设计决策的影响,你的F#代码可能最终比C#代码慢,但最终可以获得效率。


3
有趣的观点,但你需要检查不止一个运行时;在 CLI 2 中, x86 和 x64 的尾调用有很大差异;它显然已经得到加强,部分原因是为了支持 F#,但这可能会影响 C# 的性能分析。 - Marc Gravell
10
通常需要使用命令式或可变面向对象编程风格来完成这一任务。不,你想要突变以提高性能,但必须避免面向对象编程风格,而要选择类似Fortran的风格。面向对象编程也很慢... - J D
3
什么是引用(与类实例变量相比)? - colinfang
3
F#并不比C#慢,反之亦然。语言本身没有执行效率,我们讨论的是编译器的效率。随着编译技术的发展,高级语言相对于低级语言可以被更好地优化,因为通常能够更好地推理函数式源代码。现在,使用函数式语言进行编程已经进入了主流商业领域,其中一个原因是它们的执行速度正在逼近命令式语言。我们可以期待它们在未来十年内超越后者。 - Bent Tranberg
1
@BentTranberg 错了。语言定义概念,然后需要将其映射到在实际硬件上运行的程序中。其中一些概念比其他概念更难以运行。例如,如果我设计了一种只有一个指令的语言来自动理解和解决任何问题,不仅几乎不可能实现,而且速度非常非常慢;这不是编译器的问题,而是语言的问题。 - Arshia001
显示剩余2条评论


11

以下是与此主题相关的一些链接:

我记得在Robert Pickering的博客(还是Scott Hanselman?)的另一篇文章中他说,因为两种语言都运行在相同的框架上,你可以从两种语言中获得相同的性能,但有时需要“扭曲”语言的自然表达方式才能做到。我记得的例子是,他不得不扭曲F#才能获得与C#相当的性能...


6
如果您受益于F#独特的功能,比如 inline,则相反的说法也是正确的。 - J D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接