为什么不把Perl转化为C?(没事翻译了一篇文章)

为什么不把Perl转化为C?(没事翻译了一篇文章)

为什么不把Perl转化为C?(没事翻译了一篇文章)
原作者: [color=red]Mark-Jason Dominus[/color]
译者 : boOBOo
原文时间 June 27, 2001
原文 : http://www.perl.com/pub/a/2001/06/27/ctoperl.html

人们常常有这样的点子,想把Perl自动地翻译成C,然后编译C语言,这样可以使得他们地Perl程序跑得更快,因为C比Perl更快,本篇文章将解释为什么这种策略是不大可能实现的。
[b]简明摘要[/b]
Perl程序是由Perl解释器运行的。你希望能够用一个C程序完成Perl程序的功能。一个C程序要做和一个Perl程序同样的事情,就是要完成相当于Perl解释器运行你的Perl程序所要完成的大部分工作。认为这样的C程序可以比Perl解释器更快地执行是没有道理的,因为Perl解释器本身是由非常高效的C编写而成的。
以下详细地分析了几个例子。
[b]内建函数[/b]
假设你的程序需要把一个串来进行切割,并且使用Perl的split函数来执行。你现在想把这些都编译成C代码使之运行得更快一些。
这显然是不会成功得,因为split函数本身就是用C语言实现得,如果你有Perl的源代码,你就可以看到在pp。c文件里有split函数的实现;名称是pp_split。当你的Perl程序使用split的时候,Perl调用pp_split函数来完成分割。 pp_split是用C语言写成的,并且在你安装Perl的时候已经比编译成了本机的机器码。
现在,假设你想把你的Perl程序转化为C程序。你如何转化你的split程序调用呢?你唯一所能做的就是把split转化为调用C的pp_split函数,或者类似的一些程序。不会有其他的用C语言实现的split函数比Perl本身附带的pp_split更快了,年复一年的改进使得pp_split趋于极至。
同样的道理试用于Perl的其他内建函数,诸如join, printf, rand和readdir。
关于内建函数就说这么多。




   

[b]数据结构[/b...
[b]数据结构[/b]
为什么Perl一开始就比较慢呢?一个主要的原因就是它的数据结构极度的灵活性,而这种灵活的弹性对速度造成了负面的影响.
让我们仔细来看看一个重要的例子:字符串. 考虑一下这些Perl代码

[color=#0000FF]$x = 'foo';
$y = 'bar';
$x .= $y;[/color]

这段代码所做的就是把$y加到$x的后面.在C语言中,这种做法显然是非常不现实的.在C语言中,你可能一开始就需要做下这些事情:

[color=#0000FF]char *x = "foo";
char *y = "bar";[/color]

现在你就遇到麻烦了.你想把bar插入到x所指的栈后面.但是你不能这样做,因为那里没有足够的空间; x只指向能够装下4个字符的空间,你需要一个能装下7个字符那么大的空间.(C字符串总是需要一个额外的nul字符作为串的结尾.)在x后面添加y,你需要分配新的栈,然后再安排x指向它。
[color=#0000FF]char *tmp = malloc(strlen(x) + strlen(y) + 1);
strcpy(tmp, x);
strcat(tmp, y);
x = tmp;[/color]

如果x是唯一指向这个特殊栈的指针,那么一切顺利.但要是在程序的其他地方也有指针指向这个栈,那么这段代码有可能就出问题了,为什么?下面这张图片描述了我们所做的:
[b]BEFORE:[/b]
[img]http://www.perl.com/2001/06/27/graphics/cbef.gif[/img]
这里x和z是指向栈的两个指针.我们要把bar添加到字符串的结尾.但是在C代码中我们使用的C代码并没有彻底地完成我们想要的工作,因为我们分配一个新的内存区域来保存结果,然后用x指向它:
[b]AFTER x = tmp:[/b]
[img]http://www.perl.com/2001/06/27/graphics/caft.gif[/img]
可能我们想当然认为我们已经把z也指向了新的栈,但在实际操作中这是不可能的.完成添加的函数不可能知道是否还有一个所谓的z存在,以及它在哪里.可能有100个像z一样的变量全部都指向原先的那个栈(old buffer),而且没有什么好办法来使得在队列改变的时候它们保持步调一致.
Perl 提供了一种透明的字符串添加的操作方式.让我们看看这是怎么完成的吧.在Perl中,像$x那样的变量并不直接指向一个栈.而是指向一个叫做SV(‘Scalar Value’)的数据结构,而这个SV有一个指针指向这个栈,当然其中的工作机制我并没有打算解释.




   

当你让Pe...
当你让Perl把bar添加到$x后面的时候,Perl就会由指针找到栈的位置并发现栈没有足够的空间,于是Perl就把结果保存在一个新的栈里面.然后它调整在SV里的指针使其指向那个新栈,并把旧栈丢弃.
现在$x和$z都改变了.如果还有其他的变量共享SV,他们的值也都已经改变.这种技术叫做"double indirection",这也是Perl为什么支持像.=这样的操作.对于列表来说也有相似的法则;这也是为什么Perl可以支持push函数的原因.
这种灵活性是需要付出代价的:无论什么时候只要你使$x. Perl就必须由两个指针找到值:第一个指针来寻找SV结构,第二个指针来获得存放数据的栈的位置.这就意味着在Perl中使用字符串就至少需要两倍于C的操作时间.在C中,你只需要一个指针工作就可以了.
如果你想把Perl程序编译为C程序,你就面临着一个大问题.你也许支持使用诸如.=和push这样的操作,但是C对这些支持得并不是很好.只有三个办法来解决这个问题:
1.不使用 .=
这显然不是明智之举,因为在你拒绝使用所有的像.=和push这一类的Perl操作之后,你所写的程序就与Perl程序想去甚远了;看起来更像是C程序,与其如此,你不如一开始就直接用C语言来写程序.
2. 做点绝顶聪明的事情
时下聪明不足.
3. 在编译成C的代码中使用double-indirection 技术
当然可以运行,但是所获得的C代码要慢好多,因为每次你要查找变量值的时候,都得让所有指向该栈的指针调用两次.而这就是为什么Perl比较慢的原因了!Perl中的double-indirection查找操作就是用C写的,而且这些代码都已经被编译成了本机的机器码.
总而言之,如果你想在Perl代码转化为C代码中获利,这是不明智的.Perl的慢是源于灵活的数据结构.用于操作这些数据结构的代码本身就是由C写成的,如果你把Perl程序转换为C,你必须选择抛弃所有的灵活数据结构,而这样的话,你实际上就是在用C的数据结构来写C程序,或者是保留灵活性和它所造成的速度影响.基本上你不可能写出更快的数据结构,因为一旦有人知道如何在保留灵活性的同时提高结构的速度,早就在Perl本身所含有的C代码中实现了.
[b]前景[/b] [b]前景[/b]
有一点已经很明白了,虽然把Perl转化为C并不难,但程序并不会因此运行得更快.
即便如此,某些聪明过人的人可能会做出产生更快的C代码的Perl-to-C转化器.程序员则必须做出一些暗示来告诉转化器这些变量是将要如何被使用的.举个例子,假使你有一个数组@a. 对于这样的数组,Perl的初始化是什么也不做.
或许你得这样做, $a[1000000] = 'hello';或者是$a[500] .= 'foo'; 抑或是$a[500] /= 17;.这种灵活性的代价是昂贵的.但假如你事先知道这个数组只保存整型数并且不会超过1000个.你可以把这些告诉转化器,那么转化器就可以产生以下代码:
[color=#0000FF]int a[1000];[/color]
这样产成的C数组就比Perl的数组快得多.
要完成这些,你必须得非常聪明才好,你还得想出办法来向转化器说明那个@a不会有大于1000个的元素在其内,而且这些元素都是整型数,或者是想办法让你的转换器可以自动根据Perl程序内容做出判断.
人们现在开始在Perl6中计划这些特性了.举例来说,Larry Wall, Perl的作者,计划在将来Perl中实现如下的数组声明
[color=#0000FF]my int @a is dim(1000);[/color]
这样一个Perl-to-C的转换器(或者Perl本身)就可以使用更加快捷的C的机械的数组而不是那些SV.如果你有兴趣,你可以考虑加入perl6-internals 的邮件列表.
[CCB]1[/CCB] [CCB]1[/CCB]
在perl.com上找到一篇老文章,下午随便翻译了,所以不敢拿出来给大佬们嘲笑(几个老大洋文比我强多了),就放这里,很快就要复试了.
我得准备专业课了~
放到 wiki 上吧...
放到 wiki 上吧。:)
不会放,哈哈~ 而且翻得快了错得多
2,Do something...
2,Do something extremely clever
Cleverness is in short supply this month. :)

这句话是啥意思??我都搞不明白他说什么..没头没尾~
呵呵
[quote]回复给 booboo : 2,Do something......[/quote]

这句我觉得意译比较好,明显是老外的幽默嘛

这样翻译不知是否妥当?
-----------------------------------------------
2.你需要做一些极其聪明的处理

可惜聪明本月供不应求,呵呵(意思是要做出这等"聪明"的处理,实在是太复杂了)
我是这么翻译的...
我是这么翻译的阿~呵呵
-> 2. 做点绝顶聪明的事情
-> 时下聪明不足.

好像差不多.