HHVM and Hack – Can We Expect Them to Replace PHP?

Tweet
This entry is part 1 of 2 in the series HHVM and Hack

HHVM and Hack

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.

HHVM and Hack

A Look at Hack, the PHP Replacement in HHVM >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Taylor Ren

    Too many changes at a time is a bit risky.

    Learn from PHP, draw the roadmap, start to roll out with clear pictures ahead. This will be more promising.

    • http://www.bitfalls.com/ Bruno Skvorc

      Personally, I’m for total disruption. I love major changes. It’s why I switched to Phalcon overnight from Zend Framework 2, after being formally trained in it for years. Hack may not be anywhere near mature yet, but it definitely shows promise and I could see myself using it for some no-extension projects.

      Re: roadmap. Uhh, PHP has a roadmap? :)

      • Taylor Ren

        Well, this road map is not referring to PHP itself. It shall be referring to HACK per se. For example:

        1.0: wrap functions in PHP;
        2.0: introducing new grammar that can be translated to PHP (has PHP counterparts)
        3.0: introducing new grammar that can’t be translated to PHP

        Something like that.

        • http://amitgupta.in/ Amit Gupta

          Why do you assume they have no roadmap? :)

          • Taylor Ren

            I don’t konw. If there is, then great.

          • http://www.bitfalls.com/ Bruno Skvorc

            Of course there is one, they’ve just begun :)

          • http://amitgupta.in/ Amit Gupta

            Haha. :D Any sensible person (be it a software engineer or not) makes a roadmap for any project that is embarked upon. Ofcourse in case of HACK we’ll know for sure sometime later after a few releases! ;)

      • http://www.benovermyer.com/ Ben Overmyer

        How do you feel about Phalcon? I like (REALLY like) its speed, but I’m worried about community adoption. It’s been around for awhile, and it’s only now starting to gain traction…

        • http://www.bitfalls.com/ Bruno Skvorc

          It’s gaining significant traction without the help of sponsors or big companies behind them. That’s proof enough it’s intensely interesting. With the rewrite to Zephir, Phalcon will start a new age of PHP on its own front, and HHVM on the opposite. It’ll be an interesting battle to fight in, and I intend to play both sides.

          • http://amitgupta.in/ Amit Gupta

            Why would it need to be opposite HHVM? Phalcon core is compiled but the app that is made using Phalcon is still PHP & needs to be interpreted by Zend engine. So HHVM can come in and run on the app as a whole, giving it even more boost. That is unless Phalcon has plans to bring out their own engine to take care of the app code which is written in PHP.

          • http://www.bitfalls.com/ Bruno Skvorc

            Phalcon depends on the Zend Engine, and HHVM is not running it. Zend Engine extensions (like Phalcon) cannot be installed on HHVM.

          • http://amitgupta.in/ Amit Gupta

            Ah, darn! That would cut out a good many extensions in that case, no?

          • http://www.bitfalls.com/ Bruno Skvorc

            Yes. All of them. HHVM has a separate way of writing extensions for it.

          • http://amitgupta.in/ Amit Gupta

            That just sucks. Any app that uses something like ImageMagick can’t get a speed boost, eh!

          • http://www.bitfalls.com/ Bruno Skvorc
          • http://amitgupta.in/ Amit Gupta

            Interesting.

  • http://www.bitfalls.com/ Bruno Skvorc

    Thanks, fixed!

  • http://amitgupta.in/ Amit Gupta

    Looks pretty neat. HHVM already turning heads with normal PHP, pretty sure HACK will be something to watch out for.

  • Ivan Panfilov

    i don’t get it. why just not using java 8 ?

    • Kevin

      Well, we code java in php :-P . My co worker was working on a new project and he showed me his existing code base(an api backend for domain registration). I glanced the codebase and was wondering whether its C# or java. The code base is in php but it looks like java.

  • Ivan Panfilov

    Java 8 core and Serlvets it’s not to hard!
    When i need a strictly typed language – i’ll beter use Java.
    When i need rapid development and dynamic language – i use PHP.
    I hope they never make strictly typed PHP, because this will be similar castrated Java.

  • Ivan Panfilov

    Java 8 core and Serlvets it’s not to hard!
    When i need a strictly typed language – i’ll beter use Java.
    When i need rapid development and dynamic language – i use PHP.
    I hope they never make strictly typed PHP, because this will be similar castrated Java.

    • Victor Berchet

      You can start writing HACK code without adding types (ie regular PHP) for rapid dev and then add types, switch to the “strict” mode and benefit from speed improvements. More on this in the second part .

  • kapil verma

    Can’t wait for part 2 !

  • http://dan.cx/ Daniel Lo Nigro

    Thanks, great article :)

  • Dmitriy Kvashnin

    There are no reasons for PHP to be replaced with HHVM+Hack, because php-coders will produce less shitcode(so will I).