为什么PHP在Java编译为字节码文件时使用操作码caching?
从我的angular度来看,PHP和Java都有类似的结构。 首先你要编写一些高级代码,然后将代码转换为一个简单的代码格式,由VM执行。 一个区别是,PHP直接从源代码文件中工作,而Java将字节码存储在.class文件中,VM可以从中加载它们。
现在,对于PHP执行速度的要求越来越高,这让人们相信,直接使用操作代码会更好,而且每次用户点击文件时都不会经过编译步骤。
该解决scheme似乎是所谓的加速器的负载 ,基本上将编译的结果存储在caching中,然后使用caching的操作码而不是再次编译。
另一个由Facebook完成的方法是将PHP代码完全编译为不同的语言。
所以我的问题是,为什么没有人在PHP世界做Java呢? 是否有一些dynamic元素需要每次重新编译或类似的东西? 否则,在代码投入生产时编译所有东西,然后就这样工作会更聪明。
最重要的区别是JVM有一个完全覆盖字节码的明确的规范。 这使得字节码文件不仅仅是由特定的JVM实现来执行,而且是可移植的和有用的。
PHP甚至没有语言规范 。 PHP操作码是一个特定PHP引擎的实现细节,所以你不能真的对它们做任何有趣的事情,并且使它们更加可见是没有意义的。
PHP操作码与Java类文件不一样。 Java类文件是很好的指定,并可以在机器之间移植。 PHP操作码不能以任何方式移植。 例如,它们具有内存地址。 它们严格的是PHP解释器的实现细节,不应该被认为是Java字节码。
这是否必须这样? 不,可能不是。 但是PHP源代码是一团糟,PHP内部社区既没有愿望也没有政治意愿来实现这一点。 我想有一个关于将操作码caching烧入PHP 6的讨论,但PHP 6已经死亡,我不知道这个想法的状态。
参考 :我写了phc,所以在PHP实现/编译几年的时间里,我非常吝啬 。
在PHP世界中没有人正在做java所做的事情并不是真的。 像Alexey Zakhlestin的应用服务器这样的项目提供了一个更类似于java servlet容器的持久化程度(尽pipe他的灵感来源于Ruby的Rack和Python的WSGI,而不是Java)
PHP不使用操作码的标准机制。 我希望它坚持一个堆栈VM(Python,Java)或注册虚拟机(x86,perl6等)。 但它使用的东西绝对是本土的,而且在于蹭。
它使用内存中的连接列表,导致每个操作码具有 – > op1 – > op2和 – >结果。 现在每一个都是常量或临时表中的条目等这些指针不能以任何理智的方式序列化。
现在,人们已经完成了使用像pecl / bcompiler这样的项目,它将stream转储到磁盘中。
但是这些类更加复杂,这意味着有可能的代码片段
if(<conditon>) { class XYZ() { } } else { class XYZ() { } } class ABC extends XYZ {}
这意味着只有在运行时才能完成大量关于类和函数的决定 – 像Java这样的东西会在两个同名的类中窒息,而这两个类是在运行时有条件地定义的。 基本上,APC的inheritance和类caching代码可能是代码库中最复杂和最容易出错的部分。 每当一个类被caching时,所有父inheritance的成员必须在保存到操作码caching之前被清理掉。
指针问题不是无法克服的。 有一个apc_bindump,我从来没有打算修复每当重新启动完成,直接从磁盘加载整个caching项。 但是debugging所有的东西仍然需要定位所有的系统指针是很痛苦的–apache的情况太简单了,因为所有的php进程都有相同的系统指针,因为fork的行为。 旧的fastcgi版本比较慢,因为他们以后先用fork&init php – php-fpm用相反的方法修复。
但最终,PHP中真正缺less的是发明字节码格式的意愿,抛弃当前引擎和所有模块 – 使用堆栈虚拟机重写它并构buildJIT。 我希望我有时间 – fb家伙几乎在他们的嘻哈HHVM。 其中牺牲eval()更快的performance – 这是一个公平的牺牲:)
PS:我是没有时间正确更新APC 5.4的人
我认为你们所有人都是错误的。 HHVM不是另一个语言的编译器,而是虚拟机本身。 混淆是因为Facebook使用编译为C ++,但这种方法是缓慢的开发人员的要求(10分钟编译仅用于testing一些小东西)。