`
Lich_Ray
  • 浏览: 164086 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

函数式语言:我的性能没问题

阅读更多
引用
lichray 将用几天的时间写完本文系列文章的全部,剩下的文章将会发布在新建的 函数式编程の道 圈子上。这些文章将并非是从编译原理的角度来探讨函数式编程语言的文章。本文只会浅尝辄止地覆盖函数式编程语言的编译、解释优化手段,并试图让大家相信:使用函数式编程语言/风格,获得的只是表达能力上的大幅提升,而程序性能几乎不会下降。
PS: 文章中部分内容可以在《现代编译原理》这本书中找到。


一. 内存分配优化

1. 高阶函数
* 针对不纯的函数式编程语言:
不纯的函数式编程语言其实也就是比普通的命令式语言多了这个高阶函数罢了,但性能会造成下降:因为函数必须能具有普通变量的可操作性,比如作参数、返回值,函数必须作为数据的一种、被分配在堆上而不是栈上。
在处理在堆上分配函数方面,函数的创建、查找对于现在的算法来说已不是问题,关键是处理重复的函数——数据重复一般是无所谓,因为创建速度太快,而函数就不同了;如果在一个循环中创建函数,那岂不是要了函数式编程语言的命?
for (var i = 0; i < 10; i++) {
	var f = function (a) {
		return a * a
	}
	print(f(i))
}

对于“相同的函数”,有必要只保留一个。
如果两个函数是“相同”的,需要满足下面两个定义中的一个:
  • 二者从程序的源代码文本的同一处获取其函数体
  • 在使用 eval() 函数从产生程序时,二者从其参数的同一处获取其函数体

这样简单的定义已经能够处理大部分情况了(比如上面那个例程)。

* 针对纯函数式编程语言:
纯函数式编程语言的要求更加严格,决不允许出现赋值,但优化起来可以更“放心”。例如,如果编译/解释该语言需要用到中间代码,下面的优化就可以办到:
  • 进入执行上下文,重命名内部绑定的变量,用中间代码翻译所有函数体,若存在中间代码相同的函数,认为它们是同一个函数
  • 在使用 eval() 函数从产生程序时……(略)

这样一来,重复说明函数体相同(或只有内部绑定的变量命名不同)的函数将被优化——因为变量的绑定不会改变,不用担心调用两个函数造成的“结果”不同。

2. 词法作用域
对于支持词法作用域(套嵌函数)的语言来说,因为函数拥有有执行上下文,函数还必须“记住”自己是在哪儿被调用的,在那儿还声明了什么变量,因此需要一个“环境”,雪上加霜。
一些书上会这样描述一个词法作用域查找变量绑定位置的过程:
  1. 查找本级作用域是否包含该变量的绑定
  2. 如果 Result(1) 为假,转到 Step4
  3. 返回本级作用域中该变量的绑定
  4. 如果本级作用域是全局作用域(顶层),报错
  5. 对上级(调用环境)作用域应用 Step1

言下之意,函数都是被保存在一个链表中的指针所指向的,然后就像访问链表那样查找本级、上级……然后算法复杂度为 O(n)。但你觉得这可能吗?看看下面的 Scheme 代码:
(define (fact n)
	(if (= n 0)
		1
		(* n (fact (- n 1)))))

完了,要创建深度为 n 的链表啦,回忆一下 C 里面的 malloc() 的效率,一般 profile 出来的罪魁祸首就是它,不觉得毛骨悚然吗?
没有一个真正的函数式编程语言实现是在链表上分配函数的,函数被分配在哈希表中的可能性其实也不大(因为缺乏层次搜索能力),一般都是在经过特殊优化的二叉树上分配。真正的变量搜索算法也不可能那么傻,一般只是把原有的符号表“立体化”。此外,通过先进的活跃性分析技术,更有可能被重复使用的函数所需的逃逸变量将更容易被找到。

(To be continued)
分享到:
评论
4 楼 radar 2007-06-21  
Lich_Ray 写道

这个不能算是 lazy 赋值吧。在普通的 JavaScript 中可以使用 lazy 的思想但不能使用 lazy 的写法(也就是说,强迫症。不过也可以不这么挑剔,把它看成是 JavaScript 的强大)。想在 JS 里用上“写法上的”惰性运算需要 mozilla 的C版本 JS 解释器支持。

写法上的好说. 但如果不是真正的lazy 附值,那javascript 最好别放到 函数式语言 范畴.


Lich_Ray 写道

至于上文所说的闭包“可能”有的性能问题,我有理由认为,那是字符串连接的问题。你可以profile一下试试。被返回的函数事实上只创建了一次。

2. 词法作用域
创建几次不是关键,是执行过程中,
引用
因为函数拥有有执行上下文,函数还必须“记住”自己是在哪儿被调用的,在那儿还声明了什么变量,因此需要一个“环境”,雪上加霜。

这个环境的代价.

我没否定的意思,而是有些困惑.


能给说说 javascript 中的 Monad 吗?
3 楼 Lich_Ray 2007-06-21  
引用
说说上面哪个性能好点.
第二个算lazy附值吗 ? 有点强迫症。

这个不能算是 lazy 赋值吧。在普通的 JavaScript 中可以使用 lazy 的思想但不能使用 lazy 的写法(也就是说,强迫症。不过也可以不这么挑剔,把它看成是 JavaScript 的强大)。想在 JS 里用上“写法上的”惰性运算需要 mozilla 的C版本 JS 解释器支持。

至于上文所说的闭包“可能”有的性能问题,我有理由认为,那是字符串连接的问题。你可以profile一下试试。被返回的函数事实上只创建了一次。
2 楼 radar 2007-06-20  
引用
2. 词法作用域

我试着用闭包理解下,感觉闭包和你描述的感觉挺象的.
javascript中的 Execution Context   性能感觉是问题.
<SCRIPT LANGUAGE="JavaScript">
<!--
var DivTemplete=(function(){
	var templete=[
		'<div id="',
		'',   //index 1, DIV ID attribute
		'" style="position:absolute;top:',
		'',   //index 3, DIV top position
		'px;left:',
		'',   //index 5, DIV left position
        'px;width:',
		'',   //index 7, DIV width
		'px;height:',
		'',   //index 9, DIV height
		'\"><\/div>'
	];
	return (function(id,top,left,width,height){
		templete[1] = id;
		templete[3] = top;
		templete[5] = left;
		templete[7] = width;
		templete[9] = height;
		return templete.join('');
    })
})();
alert(DivTemplete('11',12,23,34,45))
//-->
</SCRIPT>

这样写可能性能没影响.
<SCRIPT LANGUAGE="JavaScript">
<!--
function outer(arg1, arg2){
    var localVar = 8;
    function inner(innerArg){
        return ((arg1 + arg2)/(innerArg + localVar));
    }
    return inner;
}
var globalVar = outer(2, 4);
alert(globalVar(2))
//-->
</SCRIPT>

这个呢,能说上面的方法性能能好吗?
1 楼 radar 2007-06-20  
<SCRIPT LANGUAGE="JavaScript">
<!--
function f(p){
    return p+1;
}
function g(p){
	return p+2;
}
alert(g(f(5)));
/**
g(f(5))
var temp=f(5);
g(temp)
*/
//-->
function gg(p){
	function ff(p){
        return p+1;
	}
	return ff(p+2);
}
alert(gg(5));
/**
  闭包包,是 lazy附值吗 ????
*/
</SCRIPT>

先让唵搞清楚高阶函数.
说说上面哪个性能好点.
第二个算lazy附值吗 ? 有点强迫症.

相关推荐

    Leetcode-solved:我对leetcode问题的解决方案

    7. **函数式编程**:Python 支持函数式编程风格,如高阶函数、闭包、装饰器等,这些在解决一些复杂问题时能够提供简洁的解决方案。 8. **模块和库的使用**:Python 中有许多内置和第三方库,如math、collections、...

    med2_MED_

    在描述中提到“程序已编写成函数形式,以使用实验台数据验证,没问题”,这表明这个程序设计用于处理实验数据,而且它的功能和性能已经过验证,确保能够正确运行。 在这个场景中,我们可以深入探讨以下几个IT知识点...

    python-3.7.4-docs-html.zip

    8. **函数式编程**:介绍了Python中的函数式编程概念,如map()、filter()、reduce()函数以及lambda表达式。 9. **性能优化**:文档中可能包含一些关于Python性能优化的建议,例如使用列表推导式代替循环,合理利用...

    没整明白这些问题 别说你学过JAVA(pdf格式)

    13. **Java 8及以后的新特性**:Lambda表达式、Stream API、Optional类、函数式接口、日期时间API(java.time包)等。 附赠的简易教程可能包含Java的基础概念、环境配置、第一个程序编写,以及逐步引导读者熟悉语言...

    轻量级Web服务器teepeedee2.zip

    John Fremlin去年在东京的Linux用户组上演示了teepeedee2的性能,他声称函数式编程语言(LISP属于函数语言)能战胜C语言。现在他的博客运行的就是teepeedee2,能即时显示用户评论,被/.之后也没出现问题。 ...

    jdk1.8,32位和64位版本,jdk1.8.0_131

    Lambda表达式与函数式接口结合,使得Java能够更好地支持函数式编程风格。 2. Stream API:这个新API提供了一种高效处理集合的方式,通过链式操作进行过滤、映射和归约等操作,使得处理数据流变得更加方便。 3. ...

    给没有耐心的同学看的 Scala 书籍.zip

    Scala 是一种多范式的编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理、云计算以及高性能计算领域。这本书“给没有耐心的同学看的 Scala 书籍”显然是针对想要快速掌握 Scala 基础的同学设计...

    App Designer:Matlab中的快速应用开发引擎

    2. **编程语言**:Matlab 拥有自己的一套编程语言,支持常见的编程概念,如变量、控制结构(例如循环和条件语句)、函数和数据结构。这使得用户可以灵活地编写算法和实现复杂的功能。 3. **数值计算**:Matlab ...

    linux_64_JDK8 (注:linux系统下的)

    JDK8引入了许多重要的新特性,如Lambda表达式、函数式接口、Stream API、日期与时间API的改进等,极大地提升了开发效率和代码的简洁性。 【压缩包子文件的文件名称列表】:“jdk1.8.0_121”是JDK8的一个具体版本号...

    java面试题

    答:折构函数式销毁一个类的函数,虚函数是为了C++的动态绑定而设计的。 描述你的编程风格? 答:类名首字母大写,常量一般全部大写,给自己的代码加注释。 控制流程? 答:控制流程一般使用if判断条件。有第二分支...

    Python3 pdf

    Python是一门多范式的编程语言,支持面向对象、命令式、函数式和过程式编程风格。由于其解释性,Python代码在运行时会被直接解释成机器码,而无需编译成二进制代码。Python支持多种编程模式,包括面向对象编程(OOP...

    gojs无水印包

    GoJS 是一个强大的JavaScript库,专门用于在Web浏览器中创建交互式图表和图形用户界面。这个"无水印包"提供了GoJS的核心功能,让用户在自己的应用中使用GoJS进行图形绘制时,不会显示任何开发者水印,为用户提供了一...

    Reactor 3中文帮助文档

    "、以及"Reactor-Extra"中关于TupleUtils、函数式接口、MathFlux、重复与重试工具和调度器的介绍。 文档中提到的一些关键术语和概念包括: - Publisher(发布者):一个提供数据的源头,它可以异步发送零个或多个...

    c++Primer第五版中文版

    C++是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化编程,也支持面向对象编程的程序设计语言。第五版中,作者详细介绍了C++的基础语法,包括变量声明、数据类型(如基本类型、指针、数组、结构体...

    dubbo-admin-2.5.8war包jdk1.8亲测可用

    这个版本引入了许多新特性,包括lambda表达式、函数式接口、Stream API、日期与时间API改进等,极大地提高了开发效率。 4. **服务治理**: 服务治理是分布式系统中的重要概念,包括服务注册与发现、健康检查、服务...

    C++学生成绩管理系统。

    C++是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化编程,也支持面向对象编程的程序设计语言。它的语法严谨,功能强大,能够进行低级内存操作,这使得它在系统编程和高性能计算领域有广泛的应用...

    Qt 5.9 C++开发指南-Qt核心特点源码

    2. **QML增强**:Qt Quick(QML)是一种声明式语言,用于构建用户界面。在Qt 5.9中,QML的性能得到提升,语法更简洁,同时增加了更多的内置元素和组件,使得UI设计更加灵活。 3. **C++ API改进**:Qt 5.9对C++ API...

    lex-manager-android

    3. **高阶函数**:Kotlin的高阶函数可以接收函数作为参数,或者返回一个函数,这在处理异步操作和函数式编程场景中非常有用。 4. **Lambda表达式和匿名函数**:Kotlin的lambda表达式使得编写简洁的回调函数成为可能...

Global site tag (gtag.js) - Google Analytics