摘要:近期,函数式编程得到了越来越多的关注,Lisp不仅重获青春还涌现出了一批新函数式编程语言。因此开发者们对函数式编程语言的运行快慢各抒己见,展开激烈讨论。本文将和大家一起讨论,函数式编程语言真的就慢吗?

由于函数式语言需要基础架构支持,这样不可避免地增加了学习汇编理论知识的成本。一流的词法闭包只有在配合垃圾回收时才能良好地工作,因为它允许值越界。

函数式语言:过度分配

请注意自己的选择。C在基准套件中扮演最小公分母,限制是可以实现的。如果在比较C语言与函数式编程语言上有一个基准,那么它肯定是一个非常简单的程序。按理说这么简单,它是没有什么实际意义的。仅仅把C作为基准的话,那么在解决更复杂的问题上,它是没有什么实际可行的解决方案。

这方面最明显的例子就是并行性。如今,多核已成为一种主流,甚至连我的手机也是多核的。在C语言中,要想实现多核并行是相当困难的,但是在函数式编程语言中会却容易实现(我比较喜欢F#)。其它例子还包括持久化数据结构,例如撤消缓冲区与纯函数数据结构是微不足道的,但在命令式语言上,这却是个非常大的工作量。

函数式语言看起来比C语言要慢,因为你仅看到基准代码在C语言里很容易去编写并且你永远不会明白基准比任务更耐人寻味,从函数式语言到Excel。然而,目前你已经能正确的识别出函数式语言的最大瓶颈是什么:过度的分配率。为什么函数式语言分配会如此严重的原因就是它被拆分成历史和内在的。

从历史上看,Lisp实现已经做了50年的装箱工作。这个特点也渗透到许多其它编程语言中,类似Lisp的中间件表示。这些年来,语言实现不断地采取装箱这种方式快速实现并发。在面向对象语言中,默认堆分配每个对象,即使明显可以采用堆栈分配。提高效率的负担是推到垃圾收集器并且在建设垃圾收集器性能上做一些努力,使它能够达到或者最大可能接近堆栈分配,通常是使用bump-allocating托管实现。我认为,应该投入更多的精力来研究函数语言设计,减少装箱和垃圾收集器设计,从而优化不同的需求。

分代式垃圾收集器

分代式垃圾收集器对语言来说,是很棒的,因为堆可以分配很多并且他们的速度也和堆栈分配差不多一样快,但是会增加其他地方的开销。如今的程序越来越多地使用像队列似地的数据结构(例如并发编程)并且让分代式垃圾收集产生一些病态行为。如果队列中的某项活得比第一代长,那么它们都会被做标记,然后所有引用的旧位置将会得到更新并且被收藏。这个大概要比它们需要的慢3倍(例如比C语言)。标记区域的收集器有可能解决这个问题,像Belway(2002)和Lmmix(2008),因为托管已经被替换成一个区域,可以被收集,就好像是一个托管所,如果它包含大部分可及值,可以被另一个区域替换并且留下时间,直到它包含一些遥不可及的值。

尽管已经存在的C++,还有Java的发明人采用泛型来消除这些错误,但这些都导致了不必要的装箱。例如,我构建一个简单的哈希表,在.NET上面的速度比JVM要快17倍。原因就是.NET并没有犯这个错误(它采用具体化泛型)并且.NET还有值类型。实际上,我认为是Lisp让Java变慢。

装箱、拆箱

所有现代式的函数式语言都是过分依赖装箱。基于JVM语言,像Clojure和Scala别无选择,因为VM甚至不能表达值类型。Ocaml(Objective Caml)在早期就揭示了类型信息,在它的编译过程和经常使用整数类型进行装箱标记并且在运行时去处理多态性。因此,Ocaml常常作为私有浮点数字被装入箱中并且一直是盒元组。在Ocaml中一个三重的字节就是一个由指针(有一个隐藏的标签嵌入在里面并且在运行时会被反复检查)和一个64位的堆上分配块头与192位的主体包含三个标记的63字节整数(3个标签,在运行时会被反复检查)。这显然是疯了。

在函数式语言上,有关拆箱优化工作已经完成但它并未真正获得牵引力。例如Mlton编译器对于ML标准来说,是一个全程序优化编译器并且很擅长拆箱优化工作。不幸的是,在运行时间之前和“长”编译时间(在现代机器上低于1秒)阻止人们使用它。

唯一的主要平台已经打破了这个趋势,但令人惊讶的是.NET却是个例外。尽管有一个Dictionary类可以高度优化键和值。微软的员工,比如Eric Lippert就继续强调值类型是根据值进行传递的,这一点很重要并且性能特点不是来源于它们内部拆箱特征。Eric的理解似乎已经被证明是错误的:越来越多的.NET程序员青睐拆箱而不是值传递。事实上,大多数结构是不可变的,因此,引用透明在值传递和引用传递之间并没有什么语义差别。性能是可见的并且结构可以提供大量的性能改进。性能结构甚至可以保存堆栈溢出并且结构常常用来避免GC延迟在商业软件上面,比如Rapid Addition's。

函数式与命令式

重分配的函数式语言的另一个原因是与生俱来的。命令式数据结构像哈希表结构使用内在巨大的整体数组。如果这些巨大的内部数组一直持续使用,将需要不断复制和更新。所以纯函数式数据结构比如平衡二叉树分裂成许多小堆,分裂成块为了便于从一个版本集合到另一个版本。

Clojure采用了一个非常巧妙的花招来解决这个问题,当集合例如dictionaries在初始化时被写,然后进行读取。在这个例子中,初始化可以使用突变来建立“幕后”结构。然而,这并不会有助于增量更新并且由此产生的集合在读取数据方面仍然比较命令式等价物慢。当然纯函数式语言在数据持久化方面明显要比命令式强。然后,很少的实际应用程序受益于持久化实践,所以这并不算是什么优势。因此,把非纯函数式语言降到命令式风格,这样就可以毫不费力的从总受益。

函数式编程语言天生就慢吗?相关推荐

  1. Java程序员必备秘籍 Scala与Clojure函数式编程语言

    编程世界就好比江湖,各种技术与思想有如各种内外家功夫在历史的舞台上纷呈登场,各领风骚.如今,自C.C++传承而来的以Java为代表的命令式语言一派可谓如日中天.门徒万千.多年来,这几门语言一直占据着T ...

  2. 函数式编程语言时代已经来临

    英国著名计算机科学家.微软首席研究员及Haskell编程语言主要贡献者Simon Peyton Jones在一次访谈中说,函数式编程语言的时代已经来临. \\ 函数式编程语言不同于大多数人所熟知的编程 ...

  3. 函数式编程语言python-10分钟学会python函数式编程

    原标题:10分钟学会python函数式编程 在这篇文章里,你将学会什么是函数范式以及如何使用Python进行函数式编程.你也将了解列表推导和其它形式的推导. 函数范式 在命令式范式中,通过为计算机提供 ...

  4. 函数式编程语言python-函数式编程语言

    最近一段时间总是听到或者看到有人谈论"函数式编程",第一次接触是在大概半年前的一次沙龙中,当时听人讲的时候,心想这有什么难理解的,函数式编程,函数嘛,那就是C呀,C++放在首位的是 ...

  5. 函数式编程语言python-Python自动化开发 - 函数式编程

    本节内容 一.函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务, 这种分解可以称之为面向过程的程序设计.函数就是面 ...

  6. 函数式编程语言python-函数式编程

    函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计的基本单元. ...

  7. 【神奇的函数式编程语言的独特功能】Lisp 的运行期修改、编译代码,并替换当前运行版本的试验...

    2019独角兽企业重金招聘Python工程师标准>>> [神奇的函数式编程语言的独特功能]Lisp 的运行期修改.编译代码,并替换当前运行版本的试验 <实用 Common Li ...

  8. lisp不是函授型语言_【神奇的函数式编程语言的独特功能】Lisp 的运行期修改、编译代码,并替换当前运行版本的试验...

    [神奇的函数式编程语言的独特功能]Lisp 的运行期修改.编译代码,并替换当前运行版本的试验 <实用 Common Lisp 编程>一书中提到一个 Lisp 神奇案例:运行在太空飞船上的一 ...

  9. 纯函数式编程语言_纯功能编程语言如何改变您的生活。

    纯函数式编程语言 by Andrea Zanin 由Andrea Zanin 纯功能编程语言如何改变您的生活. (How a purely functional programming languag ...

最新文章

  1. ffmpeg库编译加文字_ffmpeg第三方库编译记录
  2. 深度干货 | 多维分析中的 UV 与 PV
  3. ADO.NET Entity Framework如何:手动配置实体框架项目
  4. Vim和Vi的常用命令
  5. [Unity] 使用 Visual Effect Graph 制作射击枪焰特效
  6. golang 用range 创建指针数组
  7. OSChina 周日乱弹 ——局长才是真神
  8. Mybatis Generator的使用 1
  9. Log4cpp 安装和使用
  10. matlab中solver函数_matlab solve函数的用法
  11. MOEA/D 算法详解
  12. 项目管理工具ShowDoc的部署
  13. JavaSE 计算机基础知识 Java语言概述 JDK的下载,安装 HelloWorld案例 环境变量的配置 注释 关键字 标识符
  14. 习题8-5 折纸痕(Paper Folding, UVa177)
  15. QQ连连看外挂--基于LAScript
  16. 汽车维修企业管理【11】
  17. 视频虚化边框剪辑技巧分享
  18. Docker学习之路02:阿里云镜像加速器
  19. 云原生系列 六【轻松入门容器基础操作】
  20. 揭示世界本质的「机器科学家」,比深度神经网络还强?

热门文章

  1. 在IIS中启用父路径,不被黑客利用
  2. android打包工具多渠道批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案...
  3. python 语句简写_自学Python-语句之列表推导式
  4. Spark-三大数据结构之-广播变量
  5. CCIE-LAB-第十四篇-PIM Sparst+IGMP
  6. 【HDU - 1850】Being a Good Boy in Spring Festival (尼姆博弈,nim,异或前缀和)
  7. 两阶段3D目标检测网络 SIENet: Spatial Information Enhancement Network for 3D Object Detection from Point Cloud
  8. 2008r装mysql_mysql5.7.17在win2008R2的64位系统安装与配置实例
  9. vue项目编写html,从头搭建、编写一个VUE项目
  10. 遍历这些字符串,如果字符串没有包含数字的, * 就将字符串中的小写字母转成大写字母并打印字符串