功能语言中的函数开销,如Haskell或像Scala这样的混合类

时间:2013-04-24 19:47:49

标签: performance scala haskell functional-programming

来自Python,Javascript和Java等命令式语言,我经常阅读有关函数开销以及为什么要从性能角度避免 map 。显然,这些都不是函数式语言,而外国概念通常往往不那么优化,也不那么惯用。我知道调用函数会将寄存器中的值推回到堆栈,这是很昂贵的。

所以关于FP概念和语言的最近的嗡嗡声,我真的想知道Haskell如何解决这个问题?这只是编译器内联的内容吗? 除此之外,JVM上的FP-Languages(Clojure / Scala)如何解决这个问题?甚至没有一个像样的Tail-Call优化在优化FP Code方面也说明了JVM的功能。

谢谢!

2 个答案:

答案 0 :(得分:3)

我无法为Haskell提供全面的答案,但对于Scala,答案非常简单:它对字节码执行转换,例如,(简单)尾部调用实现为带有变量的循环。这本身就是任何语言必须做的事情才能实现良好的性能,因为计算机是可变的(RAM,而不是WORM!)。

将方法转换为可以传递的方法涉及创建对象,但是在JVM上对象创建很便宜,并且JVM和Scala都有或将要有技巧来避免创建该对象,除非它确实是必要的。

然后是重新使用内存与使用新内存的问题。那个很难完全解决,但JVM非常擅长快速回收内存,所以你需要支付相对适度的罚款。每次重新创建列表而不是改变其中的值。 (如果没有对旧列表的引用仍然存在,你可以改变这些值并将其称为新列表 - 我不知道GHC是否会播放这样的技巧。)最糟糕的情况是当你需要本地更新时,你在哪里在某些情况下,可以使用log(n)而不是常量工作。

当您将所有这些内容添加到一起时,(单线程)性能损失通常是适度的或可以忽略不计。

答案 1 :(得分:0)

任何基于JVM的语言都可以从JIT编译中受益,因此这已经为Scala和Clojure等语言带来了巨大的优势。

此外,scala可以从@tailrec优化中受益,该优化会将递归调用转换为循环。