Key Takeaways
- Facebook’s HHVM (HipHop Virtual Machine) and Hack programming language were developed to improve PHP’s execution speed and memory footprint, with claims of a 3x to 10x speed boost and halved memory usage.
- Hack is an evolution of the PHP language designed to be safer and more efficient, with features such as static typing and constructor argument promotion to reduce boilerplate code. It is fully supported by HHVM and is used in all of Facebook’s production servers.
- Hack introduces collections, such as Vector and Map types, which provide the same functionality as PHP arrays but with a more user-friendly object-oriented interface. It also supports lambdas, a shorthand version of closures.
- Hack’s type system is designed to catch programming errors early and generate faster code. It is statically typed and supports scalar types, and also brings support for generic programming, allowing for the creation of specialized arrays and custom types.
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.
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.
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.
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.
Hello HACK
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:
# 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:
<?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/
.
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.
More interesting HACK goodness will be introduced the following sections.
Constructor argument promotion
Not only is HACK more efficient than stock PHP when it comes to execution speed but it also focuses on improving developer efficiency.
“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:
<?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/
.
Note that facebook has proposed this feature for inclusion in stock PHP.
Collections
HACK adds support for collections. Some of the available classes will look familiar to PHP developers while there are also long-awaited additions.
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:
<?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; }
.
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/
.
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.
More on types and Generics
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
).
<?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
.
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:
<?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.
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/
.
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).
What’s next
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.
Frequently Asked Questions about HHVM and Hack
What is the main difference between PHP and HHVM?
HHVM, or HipHop Virtual Machine, is a just-in-time compiler developed by Facebook to execute programs written in PHP and Hack language. The main difference between PHP and HHVM is their execution process. PHP is an interpreted language, which means it executes the code directly, translating each statement line by line into machine code. On the other hand, HHVM uses a just-in-time (JIT) compilation approach, converting the PHP or Hack code into machine code just before it is executed. This process allows HHVM to execute the same code faster than PHP.
How does HHVM improve the performance of PHP-based applications?
HHVM improves the performance of PHP-based applications by using a just-in-time (JIT) compilation approach. This means that it converts the PHP code into machine code just before it is executed, which allows it to execute the same code faster than PHP. Additionally, HHVM uses a highly efficient execution engine that can handle large amounts of code and data, making it ideal for large-scale applications.
What is Hack language and how is it related to HHVM?
Hack is a programming language developed by Facebook that operates on the HHVM. It is designed to interoperate seamlessly with PHP, which means you can gradually convert your PHP codebase to Hack. The main advantage of Hack over PHP is that it introduces static typing, which can catch errors at compile time rather than at runtime. This makes it easier to write reliable and safe code.
How does HHVM compare to other PHP accelerators like APC or OpCache?
Unlike APC or OpCache, which are caching mechanisms that improve the performance of PHP by caching the compiled opcode, HHVM uses a just-in-time (JIT) compilation approach to execute PHP code. This means that HHVM compiles the PHP code into machine code just before it is executed, which allows it to execute the same code faster than PHP. Additionally, HHVM’s execution engine is highly efficient and can handle large amounts of code and data, making it ideal for large-scale applications.
Is it difficult to migrate from PHP to HHVM?
The migration process from PHP to HHVM can vary depending on the complexity of your codebase. However, because HHVM is designed to be a drop-in replacement for PHP, in many cases, the migration process can be as simple as installing HHVM and changing your server configuration to use HHVM instead of PHP. However, some PHP features and extensions are not supported by HHVM, so you may need to modify your code to work with HHVM.
What are the main benefits of using Hack over PHP?
The main benefits of using Hack over PHP include static typing, which can catch errors at compile time rather than at runtime, and asynchronous programming, which allows you to write non-blocking code. This makes it easier to write reliable, safe, and efficient code. Additionally, Hack is designed to interoperate seamlessly with PHP, which means you can gradually convert your PHP codebase to Hack.
Can I use HHVM with my existing PHP codebase?
Yes, HHVM is designed to be a drop-in replacement for PHP, which means you can use it with your existing PHP codebase. However, some PHP features and extensions are not supported by HHVM, so you may need to modify your code to work with HHVM.
How does HHVM handle errors and exceptions?
HHVM handles errors and exceptions in a similar way to PHP. It supports the same set of error levels as PHP, and it uses exceptions to handle errors. However, HHVM also introduces a few new error levels that are not present in PHP, such as E_RECOVERABLE_ERROR and E_USER_DEPRECATED.
What is the future of HHVM and Hack?
The future of HHVM and Hack is promising. Facebook continues to invest in the development of HHVM and Hack, and they are used extensively within Facebook. Additionally, several other large companies, such as Wikipedia and Baidu, have adopted HHVM and Hack, which indicates a growing interest in these technologies.
How can I start using HHVM and Hack?
To start using HHVM and Hack, you first need to install HHVM on your server. Once HHVM is installed, you can start writing code in Hack or convert your existing PHP codebase to Hack. There are several resources available online, including tutorials and documentation, that can help you get started with HHVM and Hack.
Victor is a professional web developer from Grenoble, France. He enjoys using modern web technologies to help his customers build efficient and maintainable web applications. He is one of the top contributors the Symfony2 PHP framework. Victor always keeps an eye on the latest technologies that could help him in his daily job, lately he has been focusing on HHVM and Dart.