2007-05-28

ErLang语法提要

ErLang语法提要

ErLang中的标点符号
ErLang语法中充满了一些约定。大写字母开头的名字(比如Address),表示一个变量,包括参数、局部变量等;小写字母开头的单词(比如ok),表示一个常量,叫做atom(原子的意思),包括常量名、函数名、模块名等。
ErLang的注释用%开头。ErLang用下划线“_”表示任意变量,类似于Java的switch语法里面的default选项。
ErLang脱胎于Prolog,不过,我觉得,ErLang语法和Haskell语法比较象,都是采用 -> 定义函数。
ErLang语句中的标点符号用法很象文章的标点符号。
整个函数定义结束用一个句号“.”;同一个函数中,并列的逻辑分支之间,用分号“;”分界;顺序语句之间,用逗号“,”分隔。
ErLang中,{ }不是表示程序块的开头和结尾,而是表示一种特殊的数据结构类型——Tuple(元组),比如,{12, 3, ok}。我们可以把Tuple理解为定长数组。
[ ] 则表示最基本的函数式编程的数据结构类型——List。List数据结构很基本,写法和用法也有一定的复杂度,不是表面上看起来那么简单,后面讲解Closure的章节会详细介绍List的最基本的构造原理。
下面我们来看一个简单的例子。
我们首先定义一个最简单的函数,把一个参数乘以10,然后加1。
times10( Number ) –>
Temp = 10 * Number,
Temp + 1.

为了说明问题,上面的代码把乘法操作和加法操作分成两个步骤。Temp = 10 * Number语句后面是逗号,因为这是两条顺序执行的语句。Temp + 1语句后面是句号,表示整个函数定义结束。而且,可以看出,ErLang没有return语句,最后执行的那条语句的执行结果就是返回值。
下面,我们把这个函数优化一下。当参数等于0的时候,直接返1;否则,就乘以10,然后加1,然后返回。这时候,我们就要用到case of逻辑分支语句,相当于java的switch语句。
times10( Number ) –>
case Number of
0 -> 1;
_ ->
Temp = 10 * Number,
Temp + 1
end.

我们来仔细观察这段ErLang程序。
当Number等于0的时候,直接返回1。由于这是一条分支语句,和后面的分支是并列的关系,所以,1的后面的标点符号是分号。后面这个分支,下划线“_”表示任何其它值,这里就表示除了1之外的任何其它数值。
需要注意的一点是,case of语句需要用end结尾,end之前不需要有标点符号。
上述代码中的case of 语句,其实就是Pattern Match的一种。ErLang的Pattern Match很强大,能够大幅度简化程序逻辑,后面进行专门介绍。
Pattern Match
Pattern Match主要有两个功能——比较分派和变量赋值。
其中,比较分派是最主要的功能。比较分派的意思是,根据参数值进行条件分支的分派。可以把比较分派功能看作是一种类似于if, else等条件分支语句的简洁强大写法。
上面的例子中,case Number of 就是根据Number的值进行比较分派。更常见的写法是,可以把Pattern Match部分提到函数定义分支的高度。于是,上述代码可以写成下面的形式:
times10( 0 ) –> 1;
times10( Number ) –>
Temp = 10 * Number,
Temp + 1.

这段代码由两个函数定义分支构成,由于两个函数分支的函数名相同,而且参数个数相同,而且两个函数定义分支之间采用分号“;”分隔,说明这是同一个函数的定义。函数式编程语言中,这种定义方式很常见,看起来形式很整齐,宛如数学公式。
这段代码的含义是,当参数值等于0的时候,那么,程序走第一个函数定义分支(即分号“;”结尾的“times10( 0 ) –> 1;”),否则,走下面的函数定义分支(即“times10( Number ) –>…”)。
第二个分支中的参数不是一个常数,而是一个变量Number,表示这个分支可以接受任何除了0之外的参数值,比如,1、2、12等等,这些值将赋给变量Number。
因此,这个地方也体现了Pattern Match的第二个功能——变量赋值。

Pattern Match的形式可以很复杂,下面举几个典型的例子。
(1)数据结构拆解赋值
前面将到了ErLang语言有一种相当于定长数组的Tuple类型,我们可以很方便地根据元素的位置进行并行赋值。比如,
{First, Second} = {1, 2}
我们还可以对复合Tuple数据结构进行赋值,比如
{A, {B, C}, D} = { 1, {2, 3}, 4 }
List数据结构的赋值也是类似。由于List的写法和用法不是那么简单,三言两语也说不清楚,还徒增困扰,这里不再赘述。
(2)assertEquals语句
在Java等语言中,我们写单元测试的时候,会写一些assert语句,验证程序运行结果。这些assert语句通常是以API的方式提供,比如,assertTrue()、assertEquals()等。
在ErLang中,可以用简单的语句达到类似于assertTrue()、assertEquals()等API的效果。
比如,ErLang中,true = testA() 这样的语句表示testA的返回结果必须是true,否则就会抛出异常。这个用法很巧妙。这里解释一下。
前面讲过,ErLang语法约定,小写字母开头的名字,都是常量名。这里的true自然也是一个常量,既然是常量,我们不可能对它赋值,那么true = testA()的意思就不是赋值,而是进行匹配比较。
(3)匹配和赋值同时进行
我们来看这样一段代码。
case Result of
{ok, Message} -> save(Message);
{error, ErrorMessage} -> log(ErrorMessage)
end.

这段代码中,Result是一个Tuple类型,包含两个元素,第一个元素表示成功(ok)或者失败(error),第二个元素表示具体的信息。
可以看到,这两个条件分支中,同时出现了常量和变量。第一个条件分支中的ok是常量,Message是变量;第二个条件分支中的error是常量,ErrorMessage是变量。
这两个条件分支都既有比较判断,也有变量赋值。首先,判断ResultTuple中的第一个元素和哪一个分支的第一个元素匹配,如果相配,那么把ResultTuple中的第二个元素赋给这个分支的第二个变量元素。即,如果Result的第一个元素是ok,那么走第一个条件分支,并且把Result的第二个元素赋给Message变量;如果Result的第二个元素是error,那么走第二个条件分支,并且把Result的第二个元素赋给ErrorMessage变量。

在Java等语言中,实现上述的条件分支逻辑,则需要多写几条语句ErLang语法可以从形式上美化和简化逻辑分支分派复杂的程序。
除了支持数相等比较,Pattern Match还可以进行范围比较、大小比较等,需要用到关键字when,不过用到when的情况,就比if else简洁不了多少,这里不再赘述。
匿名函数
ErLang允许在一个函数体内部定义另一个匿名函数,这是函数式编程的最基本的功能。这样,函数式语言才可以支持Closure。我们来看一个ErLang的匿名函数的例子。
outer( C ) –>
Inner = fun(A, B) -> A + B + C end,
Inner(2, 3).

这段代码首先定义了一个命名函数outer,然后在outer函数内部定义了一个匿名函数。可以看到,这个匿名函数采用关键字fun来定义。前面讲过,函数式编程的函数就相当于面向对象编程的类实例对象,匿名函数自然也是这样,也相当于类实例,我们可以把这个匿名函数赋给一个变量Inner,然后我们还可以把这个变量当作函数来调用,比如,Inner(2, 3)。
fun是ErLang用来定义匿名函数的关键字。这个关键字很重要。fun定义匿名函数的用法不是很复杂,和命名函数定义类似。
函数分支的定义也是类似,只是需要用end结尾,而不是用句号“.”结尾,而且fun只需要写一次,不需要向命名函数那样,每个分支都要写。比如,
MyFunction = fun(0) -> 0;
(Number) -> Number * 10 + 1 end,
MyFunction(3),
函数作为变量
匿名函数可以当作对象赋给变量,命名函数同样也可以赋给变量。具体用法还是需要借助重要的fun关键字。比如,
MyFunction = fun outer / 1

就可以把上述定义的outer函数赋给MyFunction变量。后面的 / 0表示这个outer函数只有一个参数。因为ErLang允许有多个同名函数的定义,只要参数个数不同,就是不同的函数。
我们可以看到,任何函数都可以作为变量,也可以作为参数和返回值传来传去,这些变量也可以随时作为函数进行调用,于是就具有了一定的动态性。
函数的动态调用
ErLang有一个apply函数,可以动态调用某一个函数变量。
基本用法是 apply( 函数变量,函数参数列表 )。比如,上面的MyFunciton函数变量,就可以这么调用,apply( MyFunction, [ 5 ])。
那么我们能否根据一个字符串作为函数名获取一个函数变量呢?这样我们就可以根据一个字符串来动态调用某个函数了。
ErLang中,做到这一点很简单。前面讲过,函数名一旦定义了,自然就固定了,这也类似于常量名,属于不可变的atom(原子)。所有的atom都可以转换成字符串,也可以从字符串转换过来。ErLang中的字符串实质上都是List。字符串和atom之间的转换通过list_to_atom和atom_to_list来转换。
于是我们可以这样获取MyFunciton:MyFunction = list_to_atom(“outer”)
如果outer函数已经定义,那么MyFucntion就等于outer函数,如果outer函数没有定义,那么list_to_atom(“outer”)会产生一个新的叫做outer的atom,MyFucntion就等于这个新产生的atom。
如果需要强制产生一个已经存在的atom,那么我们需要调用list_to_existing_atom转换函数,这个函数不会产生新的atom,而是返回一个已经存在了的atom。
Tuple作为数据成员集合
前面讲解函数式编程特性的时候,提到了函数式编程没有面向对象编程的成员变量,这是一个限制。
ErLang的Tuple类型可以一定程度克服这个限制。Tuple可以一定程度上担当容纳成员变量的职责。
面向对象的类定义,其实就是一群数据和函数的集合,只是集合的成员之间都有一个this指针相关联,可以相互找到。
ErLang的Tuple类型就是数据的集合,可以很自然地发挥成员变量的作用,比如,{Member1, Member2}。
读者可能会说,ErLang的函数也可以作为变量,也可以放到Tuple里面,比如, { Memer1, Member2, Funtion1, Function2}。这不就和面向对象编程一样了吗?
遗憾的是,这样做是得不偿失的。因为函数式编程没有面向对象的那种内在的this指针支持,自然也没有内在的多态和继承支持,硬把数据和函数糅合在一个Tuple里面,一点好处都没有,而且还丧失了函数作为实例对象的灵活性。
所以,函数式编程的最佳实践(Best Practice)应该是:Tuple用来容纳成员数据,函数操作Tuple。Tuple定义和函数定义加在一起,就构成了松散的数据结构,功能上类似于面向对象的类定义。Tuple + 函数的数据结构,具有多态的特性,因为函数本身能够作为变量替换;但是不具有继承的特性,因为没有this指针的内在支持。
正是因为Tuple在数据类型构造方面的重大作用,所以,ErLang专门引入了一种叫做Record的宏定义,可以对Tuple的数组下标位置命名。比如,把第一个元素叫做Address,第二个元素叫做Zipcode,这样程序员就可以这些名字访问Tuple里面的元素,而不需要按照数组下标位置来访问。
Tuple和Record的具体用法还是有一定复杂度,限于篇幅,本章没有展开说明,只提了一些原理方面的要点。
其它
ErLang还有其它语法特性和细节,不再一一赘述。有兴趣的读者,可以自行去ErLang网站(www.erlang.org)进行研究。
评论
Trustno1 2007-08-01
netpcc 写道

C++中的inline连JMP和CMP都没有了,直接把代码在本地展开,难道不会更快吗?
而且Profiling本身也要消耗性能。

上面链接的文章中有链接文章说上述的比较结果完全是应为该C++程序本身没有优化。
http://bruscy.multicon.pl/pages/przemek/java_not_really_faster_than_cpp.html
在该文作者手工优化后,C++在所有测试中胜出。




methcall.cpp

OK. So what this test actually does is it calls two methods 1 000 000 000 times each. Java uses references to access objects, so I've changed C++ code to use references too.
用.的时候,实际上不是虚函数调用,没有运行时查找编译完之后就定址了.inline优化永远是编译期的,virtual 函数是无法inline优化.而Java的可以virtual method call 优化成 inline call,这一点C++ compiler永远做不了.也就是说除非你永远不用->,否则virutal函数肯定比java慢.

I also inverted the loop direction, since comparison against 0 is faster - normally I would leave it as it was, but since this was the only benchmark in which Java Server came close to C++, I had to do something ;-) . Oh, and inverting the loop direction has no effect whatsoever on Java, so I left the code as it was.

If you look at the results, you will notice that only the poor Java Client VM actually tried to invoke the methods - both Java Server and GCC inlined the methods, which resulted in a much better performance.
这段的意思是说即便你人肉优化了所有的->操作符,速度也就是和人家的VM优化差不多.有啥意义呢?
netpcc 2007-08-01
Trustno1 写道
hyf 写道
GC是不是真的能像你说的那么强,我没有数据仅仅是猜测,如果是使用c++,小型值对象一般都在栈中不会有分配和释放。

多次看到这里有人说JIT的优化能力能针对特定的CPU,甚至产生比C++更高效的二进制码。
想请教,他的优化能去到什么程度,能识别出你的程序逻辑并产生对应的SSE指令来?

第一有GC的语言也是可以在栈中优化小值对象,比如Java的基本数据类型,做的更强的比如D,这只是语言实现上的区别,并不涉及到JIT.
第二,JIT优化与GC也没有关系.
第三,现代的JIT能比静态compiler产生更高效的代码主要集中于Polymorphic Inline Cachestype feed back两个方面.这两个技术能在语言运行时做runtime profiling.数据收集够了后,虚拟机就可以把最常用的函数调用内联到系统里,把常用函数的调用翻译成一个JMP, 跳到最有可能的函数实现那里,然后再来一个CMP,看是不是跳对了地方。只有当CMP失败的时候,系统才执行通常的动态分配.也就是说,在这两个技术面前,C++大老门在<Inside the C++ Object Model>里面绞尽脑汁鼓的各种vtalbe palcement & optimization,inline optimization技巧实际都变成了鸡肋.不过这两个技术还真称不上现代link里面的paper都是91,94年的老文,只是有赖于工业界这几年对JIT大量的投入他们的理论才逐步实现,到目前为止我看到的数据是java的method call Overhead要比c++快10倍左右.
http://kano.net/javabench/data






C++中的inline连JMP和CMP都没有了,直接把代码在本地展开,难道不会更快吗?
而且Profiling本身也要消耗性能。

上面链接的文章中有链接文章说上述的比较结果完全是应为该C++程序本身没有优化。
http://bruscy.multicon.pl/pages/przemek/java_not_really_faster_than_cpp.html
在该文作者手工优化后,C++在所有测试中胜出。
blackanger 2007-07-27
引用
大写字母开头的名字(比如Address),表示一个变量,包括参数、局部变量等;小写字母开头的单词(比如ok),表示一个常量,叫做atom(原子的意思),包括常量名、函数名、模块名等。


怎么这么反常呢?呵呵
dcaoyuan 2007-06-10
cookoo 写道
dcaoyuan 写道


是这意思。我的开源证券分析软件是百分百Java,包括实时指标运算和图形不比一些C++/Delphi的商业软件慢。里面随时产生很多很多的小对象,比如Ticks和Path2D,有些可以不管,有些我用了对象缓存。据说Java现在的垃圾回收性能甚至好过对象缓存了,不过我现在懒得去试了。


Joel前段作了一些实际交易,效果似乎不太理想,他在交易策略方面看来还是个新手,用的是传统技术分析的方法。俺现在用的是神经网络和支持向量机,对计算性能要求挺高的,Java基本上能满足我的需求,当然,现在的算法,即使用C也同样不可能再上个档次,看今后几百个核的CPU能否帮我,当然,那时我就要好把Erlang和Java比一比了。

这方面我还真有些发言权哟。


并行计算不是Erlang所长,除非计算密集部分用C写。

个股预测技术多如牛毛,大部分都是80年代流行的技术,预测命中率都差强人意,相对于宏观经济趋势来说个股趋势的预测要困难得多。现在的对冲基金都倾向于预测或创造未来驱动价格的特定事件,或者利用衍生工具及时捕捉细小的市场机会而不管未来趋势如何。对个人投资者来说可行交易理念+portfolio的构造和调整才是关键所在。


实际上有些算法从根本上来说是无法并行计算的。好在对于交易系统,我们可以对不同的策略用不同的进程来计算,这样象Erlang这种可以充分利用多核CPU的语言就可以弥补计算性能的不足。比如神经网络集群或者神经网络+遗传算法,蚁群算法等这些先天可以并行并相互通信的算法,Erlang也许特别适合。等我手头的项目差不多,我会做一些测试,比较Java, Erlang在多核的情况下性能提升的情况,第一个例子可能会是神经网络集群,

对于交易系统中算法、神经网络的应用,我当然不会去走别人已经走过的不通的路,工具还是那个工具,但对市场本质的认识决定了使用工具的效果。
Trustno1 2007-05-31
Erlang的Process类似于Active Object.很多内部的基础设施,写出来还是会像OO行为.
不过Erlang 某些idiom的确很有趣.比如说你可以把OO中的对象本身当作消息,在Process之间传来传去.也就是消息本身可以带状态,带方法,类似于一种Agent.这些Agent在不同的Process游走,然后不同的Process根据需要可以任意的装配你需要的功能.
jackyz 2007-05-31
potian 写道
题外话,从OO转变到Erlang最大的麻烦事情就是原先看什么都是对象,而在Erlang里面什么都是Process,

采用Erlang构造系统最重要的是能够构造出合适的Process,它们各自应该承担的责任,以及它们之间的消息通讯格式,所以消息通讯图和进程结构图非常重要,可以看着这些简图直接把它们转化为Erlang代码

从我现在的经验看来,采用Erlang来构造网络服务程序的开发效率将会有极大的提高,具体数字没有统计过,但通过我对现在手头一个87000多行C++代码的程序和我构造的对应原型系统来看,粗略计算代码量会在1/15-1/20左右(如果是精通的Erlang高手,估计还会有大幅度的提升)。

而稳定性、可靠性、可维护性和人月上会有更加惊人的变化。现在我相信爱立信早先的1995-1998 年3年间170万行Erlang代码能够成功,而对应的1987-95的C++系统会失败了,虚拟机、函数型语言的特性和Erlang特有的Bitsyntax、消息处理机制等等所具有的表达能力是惊人的。


深以为然,Joe Armstrong 说要“Programming by observing the real world”,虽说我学得还很浅,但这个思维方式上的转变,确实觉得是一道坎。

原来 potian 是搞视频通讯的啊,呵呵,绝对高精尖啊。
potian 2007-05-31
因为我们原先的程序在可靠性上面花了非常多的时间,我非常关心这一块,所以一般每个新功能我至少测试连续运行10个小时以上,而最新一次的整体测试已经用实际数据测试连续运行到了48小时以上。当然,由于是原型阶段,目前只是这样进行测试,我们测试室专门有10几台电脑和视频设备专门用于系统,较大的新功能增加一般会大压力测试到连续运行1周以上,新版本发布之前时间就更长了。

由于主要用于视音频传输,所以系统的数据量非常大,当初采用CNode方式测试10几个小时出现问题,我才决定外部进程完全采用TCP/IP通讯。目前测试的不但是非常大的视频流,而且采用每5秒钟一次的轮巡,频繁大量地打开和断开连接,切换视频源,特意进行破坏性试验,如定期杀死外部进程、定期模拟网络断线,没有发现任何问题。

你前面所说的setopts bug,我也没有碰到,不知道你所说的什么基础库不稳定,有没有明确所指?

------
另外,当初用CNode的时候,因为ei相关资料太少,不排除我在处理多线程的C端代码写得有问题,很难说就是Erlang本身的问题。

在Erlang ML混的中间,有一些私人通讯,其实目前采用Erlang的电信软件产品提供厂商还是不少的,特别是在欧洲,集中在VoIP和视频领域,不少系统的访问量都不小(后来我在搜索CNode的过程中,也找到过一些资料谈到和C++通讯的问题,是一些长时间稳定运行的系统)

至于爱立信自己开发的旗舰产品更加不用说了,据Joe Armstrong的邮件回复,爱立信内部至少还有几个“秘密”产品在用Erlang开发。所以对Erlang基础库的稳定性我暂时没有任何怀疑,我也很少在ML上看到对这一点的质疑。
pi1ot 2007-05-31
potian 写道
题外话,从OO转变到Erlang最大的麻烦事情就是原先看什么都是对象,而在Erlang里面什么都是Process,

采用Erlang构造系统最重要的是能够构造出合适的Process,它们各自应该承担的责任,以及它们之间的消息通讯格式,所以消息通讯图和进程结构图非常重要,可以看着这些简图直接把它们转化为Erlang代码

从我现在的经验看来,采用Erlang来构造网络服务程序的开发效率将会有极大的提高,具体数字没有统计过,但通过我对现在手头一个87000多行C++代码的程序和我构造的对应原型系统来看,粗略计算代码量会在1/15-1/20左右(如果是精通的Erlang高手,估计还会有大幅度的提升)。

而稳定性、可靠性、可维护性和人月上会有更加惊人的变化。现在我相信爱立信早先的1995-1998 年3年间170万行Erlang代码能够成功,而对应的1987-95的C++系统会失败了,虚拟机、函数型语言的特性和Erlang特有的Bitsyntax、消息处理机制等等所具有的表达能力是惊人的。


搞到最后发现erlang的基础库不够稳定时会很郁闷。
potian 2007-05-31
题外话,从OO转变到Erlang最大的麻烦事情就是原先看什么都是对象,而在Erlang里面什么都是Process,

采用Erlang构造系统最重要的是能够构造出合适的Process,它们各自应该承担的责任,以及它们之间的消息通讯格式,所以消息通讯图和进程结构图非常重要,可以看着这些简图直接把它们转化为Erlang代码

从我现在的经验看来,采用Erlang来构造网络服务程序的开发效率将会有极大的提高,具体数字没有统计过,但通过我对现在手头一个87000多行C++代码的程序和我构造的对应原型系统来看,粗略计算代码量会在1/15-1/20左右(如果是精通的Erlang高手,估计还会有大幅度的提升)。

而稳定性、可靠性、可维护性和人月上会有更加惊人的变化。现在我相信爱立信早先的1995-1998 年3年间170万行Erlang代码能够成功,而对应的1987-95的C++系统会失败了,虚拟机、函数型语言的特性和Erlang特有的Bitsyntax、消息处理机制等等所具有的表达能力是惊人的。
potian 2007-05-31
我们指并行计算的能力是Erlang的内置消息处理机制(核/CPU间或者计算机间)为构造不同方式的并行算法提供基础构架,例如可以方便地构造出符合Mapreduce算法的实现

我手头上两本并行计算的教科书开章就是讲这些问题,然后才是具体的算法、评价标准等等
-------------

现在我拿到问题发现不是对象了,而是一个个相互通讯的process,它们(或单件,或同类的进程实例)相互通讯,或者相互监督,你来我往,岂不快哉
cookoo 2007-05-30
dcaoyuan 写道


是这意思。我的开源证券分析软件是百分百Java,包括实时指标运算和图形不比一些C++/Delphi的商业软件慢。里面随时产生很多很多的小对象,比如Ticks和Path2D,有些可以不管,有些我用了对象缓存。据说Java现在的垃圾回收性能甚至好过对象缓存了,不过我现在懒得去试了。


Joel前段作了一些实际交易,效果似乎不太理想,他在交易策略方面看来还是个新手,用的是传统技术分析的方法。俺现在用的是神经网络和支持向量机,对计算性能要求挺高的,Java基本上能满足我的需求,当然,现在的算法,即使用C也同样不可能再上个档次,看今后几百个核的CPU能否帮我,当然,那时我就要好把Erlang和Java比一比了。

这方面我还真有些发言权哟。


并行计算不是Erlang所长,除非计算密集部分用C写。

个股预测技术多如牛毛,大部分都是80年代流行的技术,预测命中率都差强人意,相对于宏观经济趋势来说个股趋势的预测要困难得多。现在的对冲基金都倾向于预测或创造未来驱动价格的特定事件,或者利用衍生工具及时捕捉细小的市场机会而不管未来趋势如何。对个人投资者来说可行交易理念+portfolio的构造和调整才是关键所在。
winterwolf 2007-05-30
ErLang用在那里 ?

有点象lisp
Trustno1 2007-05-30
hyf 写道
GC是不是真的能像你说的那么强,我没有数据仅仅是猜测,如果是使用c++,小型值对象一般都在栈中不会有分配和释放。

多次看到这里有人说JIT的优化能力能针对特定的CPU,甚至产生比C++更高效的二进制码。
想请教,他的优化能去到什么程度,能识别出你的程序逻辑并产生对应的SSE指令来?

第一有GC的语言也是可以在栈中优化小值对象,比如Java的基本数据类型,做的更强的比如D,这只是语言实现上的区别,并不涉及到JIT.
第二,JIT优化与GC也没有关系.
第三,现代的JIT能比静态compiler产生更高效的代码主要集中于Polymorphic Inline Cachestype feed back两个方面.这两个技术能在语言运行时做runtime profiling.数据收集够了后,虚拟机就可以把最常用的函数调用内联到系统里,把常用函数的调用翻译成一个JMP, 跳到最有可能的函数实现那里,然后再来一个CMP,看是不是跳对了地方。只有当CMP失败的时候,系统才执行通常的动态分配.也就是说,在这两个技术面前,C++大老门在<Inside the C++ Object Model>里面绞尽脑汁鼓的各种vtalbe palcement & optimization,inline optimization技巧实际都变成了鸡肋.不过这两个技术还真称不上现代link里面的paper都是91,94年的老文,只是有赖于工业界这几年对JIT大量的投入他们的理论才逐步实现,到目前为止我看到的数据是java的method call Overhead要比c++快10倍左右.
http://kano.net/javabench/data
hyf 2007-05-30
GC是不是真的能像你说的那么强,我没有数据仅仅是猜测,如果是使用c++,小型值对象一般都在栈中不会有分配和释放。

多次看到这里有人说JIT的优化能力能针对特定的CPU,甚至产生比C++更高效的二进制码。
想请教,他的优化能去到什么程度,能识别出你的程序逻辑并产生对应的SSE指令来?
dcaoyuan 2007-05-28
cookoo 写道
hyf 写道
dcaoyuan 写道
只是我现在的选择是:计算密集和图形密集任务用Java,高并发用Erlang。Java虽然没有模式匹配,但性能方面还是足够了,而且有大把的现存开源库。当然Joel是想所有东西都在服务器端跑,估计以后图形也是服务器端生成再在Web呈现给用户。我的想法不同。

计算密集和图形密集任务适合用Java?
我见识少,没有听说Java有那些高效的数值计算和图形处理库。
而且怀疑Java在运算过程中产生大量小型对象效率会比较低。

最基础古老的运算库是Fortran写的,比如线性代数的LAPACK库
后来的大部分是C++写的,也有少数OCaml写的例子。
不过dcaoyuan说的只是密集而非大规模,够快就可以了。

因为项目的关系,我对Joel的工作也很感兴趣,他在做的似乎属于程式交易(algorithmic trading)系统。


是这意思。我的开源证券分析软件是百分百Java,包括实时指标运算和图形不比一些C++/Delphi的商业软件慢。里面随时产生很多很多的小对象,比如Ticks和Path2D,有些可以不管,有些我用了对象缓存。据说Java现在的垃圾回收性能甚至好过对象缓存了,不过我现在懒得去试了。


Joel前段作了一些实际交易,效果似乎不太理想,他在交易策略方面看来还是个新手,用的是传统技术分析的方法。俺现在用的是神经网络和支持向量机,对计算性能要求挺高的,Java基本上能满足我的需求,当然,现在的算法,即使用C也同样不可能再上个档次,看今后几百个核的CPU能否帮我,当然,那时我就要好把Erlang和Java比一比了。

这方面我还真有些发言权哟。
cookoo 2007-05-28
potian 写道
现在写程序有时候感觉到一种语言如果没有模式匹配,实在是太太太太麻烦了

前阵子Haskell社区讨论使用view pattern来增强模式匹配的建议,意思是现在的模式匹配就地匹配破坏抽象层次,而应该把模式也抽象成函数表达。F#动作更快,最新版本已经实现了类似作用的active pattern
cookoo 2007-05-28
hyf 写道
dcaoyuan 写道
只是我现在的选择是:计算密集和图形密集任务用Java,高并发用Erlang。Java虽然没有模式匹配,但性能方面还是足够了,而且有大把的现存开源库。当然Joel是想所有东西都在服务器端跑,估计以后图形也是服务器端生成再在Web呈现给用户。我的想法不同。

计算密集和图形密集任务适合用Java?
我见识少,没有听说Java有那些高效的数值计算和图形处理库。
而且怀疑Java在运算过程中产生大量小型对象效率会比较低。

最基础古老的运算库是Fortran写的,比如线性代数的LAPACK库
后来的大部分是C++写的,也有少数OCaml写的例子。
不过dcaoyuan说的只是密集而非大规模,够快就可以了。

因为项目的关系,我对Joel的工作也很感兴趣,他在做的似乎属于程式交易(algorithmic trading)系统。
hyf 2007-05-28
dcaoyuan 写道
只是我现在的选择是:计算密集和图形密集任务用Java,高并发用Erlang。Java虽然没有模式匹配,但性能方面还是足够了,而且有大把的现存开源库。当然Joel是想所有东西都在服务器端跑,估计以后图形也是服务器端生成再在Web呈现给用户。我的想法不同。

计算密集和图形密集任务适合用Java?
我见识少,没有听说Java有那些高效的数值计算和图形处理库。
而且怀疑Java在运算过程中产生大量小型对象效率会比较低。
jackyz 2007-05-28
Erlang 写道
偶觉得你这篇关于erlang语法的帖子写的即琐屑又凌乱,有些地方对erlang语法的理解有些误区。
erlang跟prolog语言没啥关系,joe armstrong花了几年的时间来找他心目中满意的能符合他要求的语言,最后打算改造prolog来实现他的想法,可是到后面应该是完全不一样了吧.
至于说erlang跟haskell语法相似也谈不上,语法上他们太多不一样了,比如最简单的元祖,列表,函数定义语法就完全不一样,还有haskell太复杂了,而erlang简单的多.
还有一个需要特别注意的是,erlang根本没有赋值的概念,只有匹配和绑定.erlang中的 = 号不要理解为赋值,在erlang中,= 的意思是匹配,就是=的左值和右值是相匹配的,不匹配就会报错,所以true = assertA()就是true表达式值匹配assertA()表达式的值.如果assertA()求值结果不是true,那么自然匹配失败.
我想到这么多,可能有谬误,还请指正.


我觉得这篇写得挺好。目前,在国内 Erlang 的中文资料极其稀少,这篇应该能够帮到很多人认识和了解 Erlang 语言。我已经向楼主发了站内消息,申请在 erlang-china.org 进行转载。

Erlang 和 Prolog 有没有关系,这个问题要看你怎么来定义“关系”这个词了。下面这些内容来自于 Joe Armstrong 的文章:
引用
......By 1990 the JAM machine was working well and had surpassed the original goal of being seventy times faster than the original Prolog interpreter. Erlang now had its own syntax (up to now it could be regarded as a dialect of Prolog) and could be regarded as a language in its own right, rather than as a dialect of Prolog......

我认为,说“ erlang 跟 prolog 语言没啥关系”,这样的提法是不合适的。

对其他的 fp 不太了解,就不发表意见了。
dcaoyuan 2007-05-28
potian 写道
现在写程序有时候感觉到一种语言如果没有模式匹配,实在是太太太太麻烦了


同感。

Joel Reymont刚把OCaml和Haskell做了一个比较,看来Haskell目前还是太学院:
http://wagerlabs.com/
说来也巧,他现在想做的事情和我想做的差不多(证券交易),只是我现在的选择是:计算密集和图形密集任务用Java,高并发用Erlang。Java虽然没有模式匹配,但性能方面还是足够了,而且有大把的现存开源库。当然Joel是想所有东西都在服务器端跑,估计以后图形也是服务器端生成再在Web呈现给用户。我的想法不同。
buaawhl
搜索本博客
其他分类
存档
最新评论