简体   繁体   English

C#/ F#性能比较

[英]C# / F# Performance comparison

Web上是否有可用的C#/ F#性能比较,以显示新F#语言的正确用法?

Natural F# code (eg functional/immutable) is slower than natural (imperative/mutable object-oriented) C# code. 自然F#代码(例如,函数/不可变)比自然(命令性/可变对象的)C#代码慢。 However, this kind of F# is much shorter than usual C# code. 但是,这种F#比通常的C#代码短得多。 Obviously, there is a trade-off. 显然,有一个权衡。

On the other hand, you can, in most cases, achieve performance of F# code equal to performance of C# code. 另一方面,在大多数情况下,您可以实现F#代码的性能等于C#代码的性能。 This will usually require coding in imperative or mutable object-oriented style, profile and remove bottlenecks. 这通常需要以命令式或可变的面向对象的方式编写代码,配置文件并消除瓶颈。 You use that same tools that you would otherwise use in C#: eg .Net reflector and a profiler. 您使用与C#中使用的相同的工具:例如.Net反射器和分析器。

That having said, it pays to be aware of some high-productivity constructs in F# that decrease performance. 话虽如此,但要注意F#中的一些高效率构造会降低性能。 In my experience I have seen the following cases: 根据我的经验,我见过以下案例:

  • references (vs. class instance variables), only in code executed billions of times 引用(与类实例变量相对),仅在执行数十亿次的代码中

  • F# comparison (<=) vs. System.Collections.Generic.Comparer, for example in binary search or sort F#比较(<=)与System.Collections.Generic.Comparer,例如二进制搜索或排序

  • tail calls -- only in certain cases that cannot be optimized by the compiler or .Net runtime. 尾调用 - 仅在某些情况下无法由编译器或.Net运行时优化。 As noted in the comments, depends on the .Net runtime. 如评论中所述,取决于.Net运行时。

  • F# sequences are twice slower than LINQ. F#序列比LINQ慢两倍。 This is due to references and the use of functions in F# library to implement translation of seq<_>. 这是由于引用和使用F#库中的函数来实现seq <_>的转换。 This is easily fixable, as you might replace the Seq module, by one with same signatures that uses Linq, PLinq or DryadLinq. 这很容易修复,因为你可以用一个使用Linq,PLinq或DryadLinq的相同签名来替换Seq模块。

  • Tuples, F# tuple is a class sorted on the heap. 元组,F#元组是在堆上排序的类。 In some case, eg a int*int tuple it might pay to use a struct. 在某些情况下,例如int * int元组,它可能需要支付使用结构。

  • Allocations, it's worth remembering that a closure is a class, created with the new operator, which remembers the accessed variables. 分配时,值得记住的是,闭包是一个用new运算符创建的类,它记住了访问过的变量。 It might be worth to "lift" the closure out, or replaced it with a function that explicitly takes the accessed variables as arguments. 可能值得“解除”闭包,或者用一个明确地将被访问的变量作为参数的函数替换它。

  • Try using inline to improve performance, especially for generic code. 尝试使用内联来提高性能,尤其是通用代码。

My experience is to code in F# first and optimize only the parts that matter. 我的经验是先用F#编码,然后只优化重要的部分。 In certain cases, it might be easier to write the slow functions in C# rather that to try to tweak F#. 在某些情况下,在C#中编写慢函数可能更容易,而不是尝试调整F#。 However, from programmer efficiency point of view makes sense to start/prototype in F# then profile, disassemble and optimize. 但是,从程序员效率的角度来看,在F#中启动/原型是有意义的,然后进行轮廓分析,反汇编和优化。

Bottom line is, your F# code might end-up slower than C# because of program design decisions, but ultimately efficiency can be obtained. 最重要的是,由于程序设计决策,您的F#代码最终可能比C#慢,但最终可以获得效率。

Here are a few links on (or related to) this topic: 以下是与此主题相关的一些链接:

What I seem to remember from another post on Robert Pickering's blog (or was it Scott Hanselman?) that in the end, because both are sitting on the same framework, you can get the same performance from both, but you sometimes have to 'twist' the natural expression of the language to do so. 我似乎还记得罗伯特皮克林博​​客上的另一篇文章(或者是斯科特汉塞尔曼?),最后,因为两者都坐在同一个框架上,你可以从两者中获得相同的表现,但有时你必须'扭曲'这种语言的自然表达。 In the example I recall, he had to twist F# to get comparable performance with C#... 在我回忆的例子中,他不得不扭曲F#以获得与C#相当的性能......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM