使用 Facebook 的 HipHop 编译器运行 CakePHP

我一直很好奇尝试将 CakePHP 编译成 C++ 代码,但一直没有时间。今年我决定尝试一下……

Facebook 在 2010 年初让 PHP 社区感到惊讶,他们宣布成功编写了 PHP 编译器,可以生成 C++ (https://developers.facebook.com/blog/post/358) 代码。PHP 是最流行的 Web 应用程序语言,它面临着来自其他语言的激烈竞争,试图将自己定位为最快的语言,但这一宣布是一个真正的游戏规则改变者,因为很难反驳编译后的机器代码的速度。

不过,很明显,使用 HipHop 编译器并不适合所有人。众所周知,您可以非常轻松地为高性能应用程序扩展 PHP,框架通常提供工具来压缩速度和促进缓存使用以使您的应用程序更快,而添加更多硬件来解决问题通常是为更多用户提供代码服务的最快且最便宜的方式。然而,在相同的硬件上让您的代码速度提高一倍,而几乎不需要成本,听起来太好了,不容错过。

echo "<?php echo 'Hello World'; ?>" > test.php
src/hphpi/hphpi test.php

1 我尝试用 Facebook 的 HipHop 编译 CakePHP 的主要动机很简单:它会起作用吗?我认为值得一试。当我有了这个想法时,论坛和推特上有很多关于哪种 PHP 框架最快的讨论,有很多有偏见的基准测试,其中大多数将 CakePHP 描绘成一个只有傻瓜才会使用的缓慢野兽。

尽管那完全是谎言,但我认为如果人们可以编译代码并获得惊人的速度而无需更改代码,这场讨论就会结束,基本上变得无关紧要。所以我开始了将 CakePHP 转换成 C++ 代码的冒险之旅,出乎意料地简单。

需求

为了执行我的测试,我使用了一个 Ubuntu 11.10 64 位虚拟机,如果您是在自己的机器上构建它,或者使用虚拟机,请确保它是 64 位的,因为 HipHop 只能在该平台上运行。此外,您还需要

public $default = array(
    'datasource' => 'HipHop.Database/HpMysql',
    'persistent' => false,
    'host' => 'localhost',
    'login' => 'root',
    'password' => 'root',
    'database' => 'cakephp',
    'prefix' => '',
    'encoding' => 'utf8',
);

2

安装

按照此页面中的安装说明进行操作,在 Ubuntu 11.10 上构建和安装 (https://github.com/facebook/hiphop-php/wiki/Building-and-Installing-on-Ubuntu-11.10),不要跳过任何步骤,列出的所有库以及要应用的补丁都是必需的。在构建所需库时,上述指南中有一些步骤存在问题。我在 GitHub 中创建了一些存储库,包括 HipHop 本身的 fork,因此您可以克隆它们,然后只构建源代码,而无需重新执行我所做的工作。这些是我的 fork

您可以下载并编译 libevent,无需应用任何自定义补丁。按照安装指南进行操作,并在需要从原始来源下载的地方使用我的 fork。

编译 HipHop 后,创建一个简单的 php 文件并测试它是否正常工作。确保您阅读了本指南 (https://github.com/facebook/hiphop-php/wiki/Running-HipHop),然后再尝试执行任何操作,务必设置环境变量 HPHP_HOMEHPHP_LIB,如该链接中所示。

测试您的构建

cd hiphop-php
export CMAKE_PREFIX_PATH=`/bin/pwd`/../
export HPHP_HOME=`/bin/pwd`
export HPHP_LIB=`/bin/pwd`/bin

我使用了解释器而不是直接编译。这就是我所做的:B0x1A1 您可以按照 wiki 页面中解释的更高级的编译代码示例进行操作。我强烈建议您先熟悉编译简单的示例并使其运行,然后再继续编译 CakePHP。

编译 CakePHP

编译应用程序最重要的部分是做好准备。我使用了一个从相当简单的数据库模式烘焙出来的简单博客来执行我的测试,使用 CakePHP 2.1-beta,并对使用 hphpi 解释器首先测试的每个功能进行了详尽的测试。

请记住,HipHop 会从您的应用程序使用的每个 php 源文件中生成一个程序。因此,编译和测试源代码最简单的方法是保留默认的 CakePHP 文件夹结构(其中 app 和 lib 位于同一根文件夹下)。为了使用解释器测试应用程序,我们需要进行一些简单的修改。

安装 HipHop 插件

第一步是安装我的 HipHop 插件 (https://github.com/lorenzo/HipHop), 只需将其放到 app/Plugin 中,并使用 CakePlugin::load(‘HipHop’) 在您的 app/Config/bootstrap.php 文件中启用它。此插件包含几个有用的脚本,可以使您的应用程序适应新的环境。

请记住,HipHop 仅支持 Mysql 和 SQLite 作为您的项目的数据库,但不幸的是,Facebook 做的 PDO 实现并不完全与原始 PHP 实现相同。因此,该插件捆绑了一个经过稍微修改的 Mysql 源代码,如果您希望您的应用程序在编译后正常工作,则需要使用它。这是一个 database.php 示例:B0x1A2

生成类映射

HipHop 没有实现任何类型的自动类加载器,因此我们需要提供一个完整的类列表,这些类将在您的应用程序中使用,这是 hphpi 解释器和编译器之间的一个很大区别。您的 CakePHP 应用程序在解释器中可以正常运行,但在编译后无法运行,如果您无法告诉它您的类在哪里。为此,该插件捆绑了一个 shell,需要在编译代码之前执行它

app/Console/cake HipHop.ClassPath

前面的命令将在 app/Config 下生成一个名为 incules.php 的文件,其中包含所有包含类的文件的硬编码 include 语句。每个文件只包含一个类非常重要,还要避免在同一个文件中组合类定义和过程代码。

下一步是将文件从 app/Plugin/HipHop/Config/webroot/index.php 复制到 app/webroot/index.php

cp `app/Plugin/HipHop/Config/webroot/index.php app/webroot/index.php

这两个文件的主要区别在于,插件提供的文件会在分派请求之前包含类映射。这使编译器能够提前知道在哪里可以找到任何需要的类。

试驾

app/Plugin/HipHop/Config/config.hdf 文件复制到您的应用程序根文件夹中,并对其进行编辑。您将在文件中找到有关其外观的注释,这是一个示例

Server {
    Port = 80
    SourceRoot = /home/lorenzo/cakephp
}

VirtualHost {
    * {
        Prefix = hiphop.local
        RewriteRules {
            * {
                pattern =    ^(.*)$
                to = /app/webroot/index.php$1
                qsa = true
                    conditions {
                            * {
                                pattern = ^/(css|js|img)/*
                                negate = true
                            }
                    }
            }
            * {
                pattern = ^/(css|js|img)/(.*)$
                to = /app/webroot/$1/$2
                qsa = true
            }
        }
    }
}

第一次使用您的应用程序源代码在服务器模式下运行解释器。转到包含您的 app 目录的根文件夹,然后执行以下命令

sudo ~/dev/hiphop-php/src/hphpi/hphpi -m server -c config.hdf

如果您没有按照指南进行操作并按照建议设置了文件夹,请相应地更改目录。运行此命令后,您将能够访问 https://127.0.0.1/ 并开始浏览您的应用程序,您还可以提供 -p 选项来选择其他端口(如 8080),如果您不想以超级用户身份运行解释器。

当您测试了应用程序中的每个功能,并对结果感到满意时,就该开始编译您的源代码了。

编译您的应用程序

编译源代码时,预计会遇到很多障碍。希望您不会遇到与我不同的问题,因此该插件已经捆绑了针对这些问题的解决方案。编译源代码需要一个完整的要包含在结果二进制文件中的文件列表,如往常一样,使用该插件来生成它

app/Plugin/HipHop/Config/scripts/generate_list

前面的命令将创建 files.list 文件。在生成列表后,使用以下命令编译您的应用程序

~/dev/hiphop-php/src/hphp/hphp --input-list=files.list -k 1 --log=3 -v "AllDynamic=true"

预计它会失败。它会抱怨缺少 PDO 常量。让我们用以下命令来解决它

app/Plugin/HipHop/Config/scripts/fixconstants

它将在 /tmp/hphp* 中运行搜索和替换函数(应该只有一个与该表达式匹配的目录),修复任何错误导出的符号。现在 cd 到 build 文件夹,然后再次开始该过程

cd /tmp/hphp* && make

耐心等待,这将需要一些时间。希望编译过程能够顺利完成,并且会生成一个名为 program 的二进制文件,准备好第一次执行它。

将程序可执行文件复制到您喜欢的任何位置,我再次将其放到我的应用程序根文件夹中。第一次运行它

./program -m server -v “Server.DefaultDocument=index.php” -c config.hdf

再次浏览您的应用程序,并确保一切正常运行,并惊叹于它的速度以及它可以同时处理的并发连接数量。

结论

使用 HipHop 运行 CakePHP 可以说是简单的,因为您可以自动化这个过程。我离自动化还很远,但我已经为大多数步骤创建了脚本。我真的很期待尝试使用新的虚拟机和即时编译器的新的 HipHop 分支。

我很有信心使用 HipHop 运行 CakePHP 时没有隐藏的错误,但我可能在这方面错了。想帮助我找到这些错误并修复它们吗?您会编译您自己的应用程序吗?在评论区留下您的想法!