五千年(敝帚自珍)

主题:【调查】大家都主要用什么写程序? -- 还是不懂

共:💬139 🌺25
全看分页树展 · 主题 跟帖
家园 回复

首先,编程语言的面向目标程度和它可以编译成本机代码的程度成反比。也就是说,编程语言的面向目标程度越高,所需要的迟后联编也就越多,它可以编译成本机代码的部分也就越少。

这个现象的原因在于编译器/联结器需要确定两样东西,变量的类型和它所需要的空间大小,来分配空间,如果在编译/联结时这两样东西无法确定,就只好用迟后联编来在运行时间解决这个问题,否则程序就无法运行了。这里,迟后联编实际上就是某种解释执行。传统的编译器是不包括迟后联编的,现代的编译器实际上是传统的编译器加上了迟后联编部分。

现实的例子就是SmallTalk,它是如此之纯的面向目标语言以至于搞传统意义上的本机编译的意义已经不大了。将SmallTalk、Java、C#和C++(注意这个顺序)相比较,可以得出一些很有趣的结论来的。

上面的讨论说明了为Java/C#搞传统意义上的本机编译器的难易程度。可以说,用传统意义上的本机编译器来编译Java/C#是不可能的(否则多态就不好办了),现在所谓的Java/C#本机编译器本质上都是静态编译和迟后联编的某种组合,并且随着高级面向目标特性的增多,迟后联编的部分也要增多。

这个结论的一个推论就是,程序的运行性能和它的编程实现语言的面向目标程度是成反比的。该推论的一个现实例子就是Java程序的性能永远不可能赶上C++程序的性能,原因就是Java是比C++更纯的面向目标语言。

其次,讨论一下有无可能从软件方面大幅度提高虚拟机的性能。

只要程序是解释执行的,就必然存在一个中间码到机器码的转换过程。简单地讲,如果把一个程序的全部中间码都一次性转变为机器码后应该是可以消除二者之间的性能差异的(.Net提供了一个这样的工具ngen),但是代价则是可移植性的丧失。否则就只能够动态地将中间码变换为机器码,变换的次数越多,性能损失也就越大,改进办法就是所谓的生成的机器码高速缓存,利用大的机器码缓存来减少重复解释中间码的机会。

这里提高性能的关键是所谓的代码跟踪分析和由此而得到的动态优化所生成的机器码,使生成的机器码尽可能地简洁以至于可以充分利用机器的硬件缓存,这样理论上是有可能产生性能超过本机编译的代码的,但是它受限制于程序的类型和算法,而且要考虑代码跟踪分析和动态优化的开销。

就我个人而言,我觉得最好的解决方案就是微软的.Net的ngen,这样既提供了可移植性,又提供了在目标硬件平台确定的情况下一次性彻底将中间码转换为机器码的能力。


本帖一共被 2 帖 引用 (帖内工具实现)
全看分页树展 · 主题 跟帖


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河