38

在我看来,PHP 和 Java 都有相似的结构。首先,您编写一些高级代码,然后必须将其转换为更简单的代码格式才能由 VM 执行。一个区别是,PHP 直接从源代码文件工作,而 Java 将字节码存储在 .class 文件中,VM 可以从中加载它们。

现在对快速执行 PHP 的要求越来越高,这导致人们相信直接使用操作码而不是每次用户点击文件时都经过编译步骤会更好。

解决方案似乎是加载所谓的 Accelerators,它基本上将编译的结果存储在缓存中,然后使用缓存的操作码而不是再次编译。

Facebook 采用的另一种方法是将 PHP代码完全编译为另一种语言。

所以我的问题是,为什么 PHP 世界中没有人像 Java 那样做?是否有一些动态元素真的需要每次都重新编译或类似的东西?否则,当代码投入生产时编译所有内容然后就可以使用它会更聪明。

4

5 回答 5

52

最重要的区别是 JVM 有一个完全覆盖字节码的明确规范。这使得字节码文件具有可移植性和实用性,而不仅仅是由特定的 JVM 实现执行。

PHP 甚至没有语言规范。PHP 操作码是特定 PHP 引擎的实现细节,所以你不能用它们做任何有趣的事情,而且让它们更明显也没什么意义。

于 2012-05-23T09:17:35.543 回答
12

PHP 操作码与 Java 类文件不同。Java 类文件被很好地指定,并且可以在机器之间移植。PHP 操作码不能以任何方式移植。例如,它们具有内置的内存地址。它们严格来说是 PHP 解释器的实现细节,不应被视为 Java 字节码之类的东西。

一定要这样吗?不,可能不是。但是 PHP 源代码是一团糟,PHP 内部社区既没有愿望也没有政治意愿来实现这一点。我认为有人谈论将操作码缓存烘焙到 PHP 6 中,但 PHP 6 死了,我不知道这个想法的状态。

参考:我写了phc,所以我在 PHP 实现/编译方面已经有几年的时间了。

于 2012-05-29T20:39:27.270 回答
4

PHP 世界中没有人在做 java 所做的事情,这并不完全正确。Alexey Zakhlestin 的 appserver等项目提供了某种程度的持久性,更类似于 java servlet 容器(尽管他的灵感更多是 Ruby 的 Rack 和 Python 的 WSGI,而不是 Java)

于 2012-05-23T09:31:01.790 回答
3

PHP 不使用操作码的标准机制。我希望它要么粘在堆栈 VM(python、java)或寄存器 VM(x86、perl6 等)上。但它使用了绝对本土的东西,问题就在这里。

它使用内存中的连接列表,这导致每个操作码具有 ->op1 ->op2 和 ->result。现在每个都是常量或临时表中的条目等。这些指针不能以任何理智的方式序列化。

现在,人们已经使用 pecl/bcompiler 之类的项目完成了这项工作,它确实将流转储到磁盘中。

但是这些类使这变得更加复杂,这意味着存在潜在的代码片段,例如

if(<conditon>)
{
   class XYZ() { }
}
else 
{
   class XYZ() { }
}

class ABC extends XYZ {}

这意味着大量关于类和函数的决定只能在运行时完成——像 Java 这样的东西会阻塞在两个同名的类上,它们是在运行时有条件地定义的。基本上,APC 的继承和类缓存代码可能是代码库中最复杂和最容易出错的部分。每当一个类被缓存时,所有父继承成员都必须被清除,然后才能保存到操作码缓存中。

指针问题并非不可克服。有一个 apc_bindump ,我从来没有费心修复它,以便在重新启动时直接从磁盘加载整个缓存条目。但是调试所有这些以获得仍然需要定位所有系统指针的东西是很痛苦的 - apache 案例太容易了,因为由于 fork 行为,所有 php 进程都具有相同的系统指针。旧的 fastcgi 版本速度较慢,因为它们通常先 fork 然后再初始化 php - php-fpm 通过相反的方式解决了这个问题。

但最终,PHP 中真正缺少的是发明一种字节码格式、抛弃当前引擎和所有模块的意愿——使用堆栈 VM 重写它并构建 JIT。我希望我有时间——fb 的人几乎都带着他们的 hiphop HHVM。这牺牲了 eval() 以获得更快的性能 - 这是一个公平的牺牲:)

PS:我是没时间正确更新APC for 5.4的人

于 2012-06-01T16:14:44.350 回答
3

我想你们都被误导了。HHVM 不是编译器,另一种语言是虚拟机本身。混淆是因为facebook使用编译成c++,但这种方法是为了满足开发人员的要求而慢慢地(十分钟编译只是为了测试一些小东西)。

于 2013-12-29T15:44:08.090 回答