Facebook started to work on HipHop for PHP in 2008. Their goal was to speed up the PHP execution speed and the first version of the project was composed of the tandem HPHPc/HPHPi. HPHPc is a PHP to C++ transpiler which was used to deploy the code to the production servers while HPHPi was an interpreter used during development and debug stages.
Facebook从2008年开始致力于HipHop for PHP。他们的目标是加快PHP执行速度,该项目的第一个版本由串联的HPHPc / HPHPi组成。 HPHPc是从PHP到C ++的编译器,用于将代码部署到生产服务器,而HPHPi是在开发和调试阶段使用的解释器。
HPHPc did a good job on improving performance but it was not without issues: maintaining both HPHPc and HPHPi in sync proved to be cumbersome plus some differences still existed between the transpiled code vs the interpreted one. That's why back in 2010 Facebook decided to go for another approach and created HHVM – a new virtual machine designed to replace the Zend Engine used by PHP. By the end of 2012 HHVM achieved performance parity with the former HPHPc and soon surpassed it.
HPHPc在提高性能方面做得很好,但这并非没有问题:保持HPHPc和HPHPi同步非常麻烦,而且在转译的代码与解释的代码之间仍然存在一些差异。 因此,在2010年,Facebook决定采用另一种方法,并创建了HHVM –一种旨在取代PHP使用的Zend Engine的新虚拟机。 到2012年底,HHVM达到了与以前的HPHPc相当的性能,并很快超过了它 。
HHVM is intended to achieve both parity with the Zend Engine features and best possible performances. Facebook claims a 3x to 10x speed boost and 1/2 memory footprint by switching from PHP+APC to HHVM. Of course this is really application dependent (10x being for the FB code base). This article will not focus on parity nor performances as plenty of resources are already available, check the HHVM blog or google for "hhvm benchmark". To find out more about HipHop and HHVM in general, read the previous SitePoint articles about it.
HHVM旨在实现与Zend Engine功能的奇偶校验和最佳性能。 从PHP + APC切换到HHVM,Facebook声称将速度提高了3倍至10倍,并占用了1/2的内存。 当然,这实际上取决于应用程序(10x用于FB代码库)。 由于没有足够的资源,本文将不关注奇偶校验或性能,请查看HHVM博客或google以获取“ hhvm基准” 。 要大致了解有关HipHop和HHVM的更多信息,请阅读有关它的先前SitePoint文章 。
Instead this article will focus on HACK which is an evolution of the PHP language designed to be safer, to enable better performance and to improve developer efficiency. Note that both HACK and PHP are equally supported by the HHVM. Despite the fact that HACK is in use at Facebook on all the production servers, only little info has leaked for now. In a nutshell, HACK is Facebook's PHP6 – it proposes to fix most of what's wrong with PHP today, while adding some new features like static typing along the way.
取而代之的是,本文将重点介绍HACK,它是PHP语言的一种改进,旨在更加安全,实现更好的性能并提高开发人员的效率。 请注意,HHVM同样支持HACK和PHP。 尽管所有生产服务器上的Facebook都在使用HACK,但目前只有很少的信息泄漏。 简而言之,HACK是FacebookPHP6 –它提出了解决当今PHP大多数问题的方法,同时增加了一些新功能,例如静态类型。
Not all the tools and almost no documentation for HACK have been released as of today. However the latest available HHVM source code already supports HACK. You can install a Vagrant virtual machine to start experimenting with HACK and run the code snippets from this article:
到今天为止,尚未发布所有的工具以及关于HACK的几乎所有文档。 但是,最新的可用HHVM源代码已经支持HACK。 您可以安装Vagrant虚拟机以开始尝试HACK并运行本文中的代码段:
# Vagrant should be installed on your machine
$ git clone https://github.com/vicb/hhvm-vagrant.git
$ cd hhvm-vagrant
$ vagrant up
You are now ready to write your first HACK program:
现在您可以编写第一个HACK程序了:
<?hh
require "/vagrant/www/xhp/php-lib/init.php";
$hello = "Hello HACK!";
echo <html>
<head>
<title>{$hello}!</title>
</head>
<body>
<h1>{$hello}</h1>
</body>
</html>;
This sample is available in your clone of the vagrant VM (located at www/hello/index.php
). You can see the result by pointing your browser to http://localhost:8080/hello/
.
您可以在您的无业游民的VM克隆中找到此示例(位于www/hello/index.php
)。 通过将浏览器指向http://localhost:8080/hello/
可以看到结果。
A HACK application starts with the <?hh
tag located at the very start of your source file – note that there is no closing tag in HACK. This sample is pretty self-explanatory, the only noteworthy point is that is uses XHP, an XML markup language which is also available as a stock PHP extension. More about XHP later in this article.
HACK应用程序以源文件开头的<?hh
标记开头-请注意,HACK中没有结束标记。 该示例是不言自明的,唯一值得注意的一点是使用XHP (一种XML标记语言),它也可以作为库存PHP扩展使用 。 本文稍后将详细介绍XHP。
More interesting HACK goodness will be introduced the following sections.
以下各节将介绍更有趣的HACK优点。
Not only is HACK more efficient than stock PHP when it comes to execution speed but it also focuses on improving developer efficiency.
在执行速度方面,HACK不仅比普通PHP更高效,而且着重于提高开发人员的效率。
"Constructor argument promotion" is one of the features helping reducing boilerplate code. Indeed, a common pattern when creating a class in PHP is first to declare the properties and then assign all of them straight from constructor arguments. With HACK, adding the visibility as a constructor argument modifier is enough for both declaring the property and initializing it. It makes the code more concise:
“构造函数自变量提升”是有助于减少样板代码的功能之一。 确实,在PHP中创建类时,常见的模式是先声明属性,然后直接从构造函数参数中分配所有属性。 使用HACK,将可见性添加为构造函数参数修饰符就足以声明属性和对其进行初始化。 它使代码更简洁:
<?hh
class PHPClass {
public $pub;
protected $pro;
private $pri;
public function __construct($pub, $pro, $pri) {
$this->pub = $pub;
$this->pro = $pro;
$this->pri = $pri;
}
}
// object(PHPClass)#6 (3) { ["pub"]=> string(3) "pub" ["pro":protected]=> string(3) "pro" ["pri":"PHPClass":private]=> string(3) "pri" }
var_dump(new PHPClass('pub', 'pro', 'pri'));
// The same class written in HACK is much more concise
// thanks to constructor argument promotion.
class HHClass {
public function __construct(public $pub, protected $pro, private $pri) {}
}
// object(HHClass)#6 (3) { ["pub"]=> string(3) "pub" ["pro":protected]=> string(3) "pro" ["pri":"HHClass":private]=> string(3) "pri" }
var_dump(new HHClass('pub', 'pro', 'pri'));
The sample code for this section is located at www/promotion/index.php
and you can see its output by pointing your browser to http://localhost:8080/promotion/
.
本节的示例代码位于www/promotion/index.php
,您可以通过将浏览器指向http://localhost:8080/promotion/
来查看其输出。
Note that facebook has proposed this feature for inclusion in stock PHP.
请注意,facebook已提议将此功能包含在库存PHP中 。
HACK adds support for collections. Some of the available classes will look familiar to PHP developers while there are also long-awaited additions.
HACK添加了对集合的支持。 对于PHP开发人员,某些可用的类看起来会很熟悉,同时也期待已久。
The Vector
and Map
types are an augmented version of PHP arrays in the sense that they provide the same functionality but expose a nice object oriented interface which is missing in stock PHP:
Vector
和Map
类型是PHP数组的增强版本,从某种意义上说,它们提供了相同的功能,但暴露了漂亮的面向对象的接口,而该接口在现有PHP中是缺少的:
<?hh
require "/vagrant/www/xhp/php-lib/init.php";
$v = Vector {"d", "c", "b"};
$v->add("a");
$v->reverse();
$v = $v->map(($_) ==> strtoupper($_))->filter(($_) ==> strcmp($_, "D") < 0);
$items = <ul />;
foreach ($v as $i) {
$items->appendChild(<li>{$i}</li>);
}
echo <div>Vector:{$items}</div>; // A, B, C
$m = Map {"a" => 1, "b" => 2};
$m->add(Pair {"d", 4});
echo <div>Map:
<ul>
<li>contains "a": {$m->contains("a") ? "yes" : "no"}</li> // yes
<li>contains "c": {$m->contains("c") ? "yes" : "no"}</li> // no
<li>size: {$m->count()}</li> // 3
</ul>
</div>;
In this sample you can also notice the introduction of "lambdas". They are a shorthand version of closures, ($args) ==> $result
being the equivalent to function($args) { return $result; }
.
在此示例中,您还可以注意到引入了“ lambda”。 它们是闭包的简写形式, ($args) ==> $result
等于function($args) { return $result; }
function($args) { return $result; }
。
The sample code for this section is located at www/collections/index.php
and you can see its output by pointing your browser to http://localhost:8080/collections/
.
本节的示例代码位于www/collections/index.php
,您可以通过将浏览器指向http://localhost:8080/collections/
来查看其输出。
HACK also provides a Set
type – a collection of unique elements, a "Frozen" immutable variant for each of the above described types (to allow for further speed optimizations) a bunch of Iterators and many useful methods. You can learn more by checking the collections IDL file.
HACK还提供了Set
类型–唯一元素的集合,上述每种类型的“ Frozen”不可变变体(以实现进一步的速度优化),一堆迭代器和许多有用的方法。 您可以通过检查集合IDL文件来了解更多信息。
PHP 5 has introduced type hinting which allows functions to force parameters to be objects, interfaces, arrays or callable. HACK goes even further, it is statically typed and supports scalar types (i.e. int
, num
or string
).
PHP 5引入了类型提示,它允许函数将参数强制为对象,接口,数组或可调用。 HACK更进一步,它是静态类型的,并支持标量类型(即int
, num
或string
)。
<?hh
require "/vagrant/www/xhp/php-lib/init.php";
set_error_handler(function ($no, $str) {
$func = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function'];
$line = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['line'];
echo <p>ERROR(calling "{$func}()" on l.{$line}) : {$str}</p>;
});
function echo_upper(string $s) {
echo (strtoupper($s));
}
echo_upper("lower"); // LOWER
echo_upper(5); // ERROR(calling "echo_upper()" on l.16) : Argument 1 passed to echo_upper() must be an instance of string, int given
echo_upper(null); // ERROR(calling "echo_upper()" on l.17) : Argument 1 passed to echo_upper() must be an instance of string, null given
In this code sample, the echo_upper
function expects a string
as the first argument. Passing an int
or null
would trigger an error. null
value could have been allowed by prepending a ?
to the type, i.e. ?string
.
在此代码示例中, echo_upper
函数期望将string
作为第一个参数。 传递int
或null
会触发错误。 可以通过在?
前面加上一个null
值来允许它 类型,即?string
。
HACK also brings support for generic programming via Generics similar to those of Java. For example you can specialize a regular array
by specifying the type of its elements:
HACK还通过类似于Java的泛型为通用编程带来了支持。 例如,您可以通过指定常规array
的元素类型来使其专门化:
<?hh
function sum(array<int> $a) {
return array_reduce($a, ($sum, $i) ==> $sum + $i);
}
echo <p>sum([1, 2, 3]) = {sum([1, 2, 3])}</p>; // sum([1, 2, 3]) = 6
Using Generics with built-in types is great but you can also implement your own types using Generics:
将泛型与内置类型一起使用非常好,但是您也可以使用泛型来实现自己的类型:
<?hh
class Generics<T as Countable> {
private ?T $t;
public function get() : ?T {
return $this->t;
}
public function set(?T $t) {
$this->t = $t;
}
public function __toString() {
return var_export($this->t, true);
}
public function count() {
return $this->t ? $this->t->count() : 0;
}
}
$type = new Generics();
$type->set(Vector {1, 2, 3});
echo <div>$type
<ul>
<li>= {$type}</li> <!-- HH\Vector { 1, 2, 3, } -->
<li>size = {$type->count()}</li> <!-- 3 -->
</ul></div>;
This code sample is not really useful by itself but nevertheless it introduces a few interesting concepts. HHVM makes possible to: – constrain the acceptable types: <T as Countable>
means that the contained type must implement the \Countable
interface which is a requirement dictated by the count()
method, – specify the property types, The $t
property must be of T type. The leading ?
means that $t
could also be null, – specify the return type of a method (or function), public function get() : ?T
means that get
will return a T type, – constrain the argument, the set()
method would only allow a T type which could possibly be null.
此代码示例本身并不是真正有用的,但是它引入了一些有趣的概念。 HHVM可以:–限制可接受的类型: <T as Countable>
表示所包含的类型必须实现\Countable
接口,这是count()
方法所规定的要求,–指定属性类型, $t
属性必须属于T型。 领先?
表示$t
也可以为null,–指定方法(或函数)的返回类型, public function get() : ?T
表示get
将返回T类型,–约束参数, set()
方法将只允许一个T类型,该类型可能为null。
The sample code for this section is located at www/types/index.php
and you can see its output by pointing your browser to http://localhost:8080/types/
.
本节的示例代码位于www/types/index.php
,您可以通过将浏览器指向http://localhost:8080/types/
来查看其输出。
The HACK type system is really powerful and serves 2 purposes. The first one is to catch programming errors as early as possible and the second is to generate faster code (more on that in the next part).
HACK类型系统功能强大,有两个用途。 第一个是尽早发现编程错误,第二个是生成更快的代码(在下一部分中有更多介绍)。
The next part of this article will show you more about HACK's statically typed nature, how HACK makes asynchronous code execution easy, the XHP markup language and some more exciting features.
本文的下一部分将向您展示有关HACK的静态类型的本质,HACK如何使异步代码执行变得容易,XHP标记语言以及其他更令人兴奋的功能。