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的人