at Liip - @chregu on Twi!er (and almost everywhere else) - PHP “Core” developer (when I was young ;) ) ! - I work together with a Liip team on a big project for the Migros - We use HHVM on that project in production
Machine - A PHP Virtual Machine wri!en by Facebook - Goal: Make it much faster than “Zend” PHP - And be compatible to PHP (one way at least) - Language additions to PHP, called Hack - Open sourced in late 2011 (PHP License) - Mainly wri!en in C++, PHP and OCaml
with HPHP - A PHP to C++ compiler => HPHPc - Compiling to a (huge) binary - Up to 6x faster than Zend PHP - Also: HPHi (for local dev) and HPHPd (for debugging) - Deprecated in 2013 ! - HHVM began in 2010 - Bytecode compiler, then JIT to native code - Full support of PHP 5.4
fast-cgi - Version at 3.0.1 - Supports many PHP frameworks out of the box (see h!p:// hhvm.com/frameworks) - Supports many extension (new ones since 3.0 for example XSLT, imagick and mysqli) - Hack is documented - Quite easily installable on Debian based systems - Runs anywhere which is 64-bit x86 linux (on os x kind of, Windows and ARM support is coming)
everything ! export ABI=64 export LD_LIBRARY_PATH=/srv/www/vhosts/api/hhvm/lib64:/srv/www/vhosts/api/hhvm/lib:$LD_LIBRARY_PATH export PATH=/srv/www/vhosts/api/hhvm/bin/:$PATH export SRCFOLDER=/srv/www/vhosts/api/hhvm/src ! mkdir -p $SRCFOLDER cd $SRCFOLDER ! # INSTALL all the dependencies, you only have to do this once ! #CMAKE ! cd $SRCFOLDER wget http://www.cmake.org/files/v2.8/cmake-2.8.12.1.tar.gz tar -xzf cmake-2.8.12.1.tar.gz cd cmake ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install ! #gmp ! cd $SRCFOLDER wget https://gmplib.org/download/gmp/gmp-5.1.3.tar.bz2 tar -xjf gmp-5.1.3.tar.bz2 cd gmp-5.1.3 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install ! #mpfr ! cd $SRCFOLDER wget http://www.mpfr.org/mpfr-current/mpfr-3.1.2.tar.bz2 cd mpfr-3.1.2 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-gmp=/srv/www/vhosts/api/hhvm/ make install ! #mpc ! cd $SRCFOLDER wget http://www.multiprecision.org/mpc/download/mpc-1.0.1.tar.gz cd mpc-1.0.1 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-gmp=/srv/www/vhosts/api/hhvm/ make install ! ! ! !
http://isl.gforge.inria.fr/isl-0.12.tar.bz2 tar -xjf isl-0.12.tar.bz2 cd isl-0.12 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-gmp-prefix=/srv/www/vhosts/api/hhvm/ make install ! #GCC ! cd $SRCFOLDER wget ftp://ftp.gwdg.de/pub/misc/gcc/releases/gcc-4.8.2/gcc-4.8.2.tar.bz2 tar -xjf gcc-4.8.2.tar.bz2 cd gcc-4.8.2 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-isl=/srv/www/vhosts/api/hhvm --with-gmp=/srv/www/vhosts/api/hhvm/ --with-mpc=/srv/www/vhosts/api/hhvm/ mpfr=/srv/www/vhosts/api/hhvm/ make install ! #bzip ! cd $SRCFOLDER cd bzip2-1.0.6 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make -f Makefile-libbz2_so make install PREFIX=/srv/www/vhosts/api/hhvm/ cd .. #python (needed for boost) ! cd $SRCFOLDER wget http://www.python.org/ftp/python/2.6.9/Python-2.6.9.tgz tar -xzf Python-2.6.9.tgz cd Python-2.6.9 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --enable-shared make install ! #boost ! cd $SRCFOLDER wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.bz2/download tar -xjf boost_1_55_0.tar.bz2 cd boost_1_55_0 ls ./bootstrap.sh --with-python=/srv/www/vhosts/api/hhvm/bin/python --prefix=/srv/www/vhosts/api/hhvm ./b2 ./bjam --layout=system install ! ! !
https://github.com/downloads/libevent/libevent/libevent-1.4.14b-stable.tar.gz tar -xzf libevent-1.4.14b-stable.tar.gz cd libevent-1.4.14b-stable cat ../hhvm/hphp/third_party/libevent-1.4.14.fb-changes.diff | patch -p1 ./autogen.sh autoreconf --force --install ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! #libcurl ! cd $SRCFOLDER mkdir /srv/www/vhosts/api/hhvm/etc/curlssl wget -O /srv/www/vhosts/api/hhvm/etc/curlssl/cacert.pem http://curl.haxx.se/ca/cacert.pem wget http://curl.haxx.se/download/curl-7.36.0.tar.gz tar -xzf curl-7.36.0.tar.gz cd curl-7.36.0 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-ca-bundle=/srv/www/vhosts/api/hhvm/etc/curlssl/cacert.pem make make install ! #google glog ! cd $SRCFOLDER wget https://google-glog.googlecode.com/files/glog-0.3.3.tar.gz tar -xzf glog-0.3.3.tar.gz cd glog-0.3.3 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! #memcached ! cd $SRCFOLDER wget http://www.memcached.org/files/memcached-1.4.16.tar.gz tar -xzf memcached-1.4.16.tar.gz ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! ! ! ! ! !
cd $SRCFOLDER wget https://launchpad.net/libmemcached/1.0/1.0.16/+download/libmemcached-1.0.16.tar.gz tar -xzf libmemcached-1.0.16.tar.gz cd libmemcached-1.0.16 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --with-memcached=/srv/www/vhosts/api/hhvm/bin/memcached make make install ! #jemalloc ! cd $SRCFOLDER wget http://www.canonware.com/download/jemalloc/jemalloc-3.4.1.tar.bz2 tar -xjf jemalloc-3.4.1.tar.bz2 cd jemalloc-3.4.1 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! #tbb ! cd $SRCFOLDER wget --no-check-certificate https://www.threadingbuildingblocks.org/sites/default/files/software_releases/source/tbb42_20131118oss_src.tgz tar -xzf tbb42_20131118oss_src.tgz cd tbb42_20131118oss make mkdir -p /srv/www/vhosts/api/hhvm/include/serial cp -a include/serial/* /srv/www/vhosts/api/hhvm/include/serial/ mkdir -p /srv/www/vhosts/api/hhvm/include/tbb cp -a include/tbb/* /srv/www/vhosts/api/hhvm/include/tbb/ cp build/linux_intel64_gcc_cc4.8.2_libc_kernel3.0.82_release/libtbb.so.2 /srv/www/vhosts/api/hhvm/lib64/ ln -s /srv/www/vhosts/api/hhvm/lib64/libtbb.so.2 /srv/www/vhosts/api/hhvm/lib64/libtbb.so ! # mysql ! cd $SRCFOLDER wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.15.tar.gz tar -xzf mysql-5.6.15.tar.gz cd mysql-5.6.15 cmake . -DWITHOUT_SERVER=ON -DCMAKE_INSTALL_PREFIX=/srv/www/vhosts/api/hhvm make make install cd .. ! ! ! ! !
https://bitbucket.org/libgd/gd-libgd/downloads/libgd-2.1.0.tar.bz2 tar -xjf libgd-2.1.0.tar.bz2 cd libgd-2.1.0 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install ! #expat ! cd $SRCFOLDER wget http://downloads.sourceforge.net/project/expat/expat/2.1.0/expat-2.1.0.tar.gz tar -xzf expat-2.1.0.tar.gz cd expat-2.1.0 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install ! #icu ! cd $SRCFOLDER wget http://download.icu-project.org/files/icu4c/52.1/icu4c-52_1-src.tgz tar -xzf icu4c-52_1-src.tgz cd icu/source ./configure --prefix=/srv/www/vhosts/api/hhvm/make install ! #libmcrypt ! cd $SRCFOLDER wget http://downloads.sourceforge.net/project/mcrypt/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.bz2 tar -xjf libmcrypt-2.5.8.tar.bz2 cd libmcrypt-2.5.8 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! #openssl ! cd $SRCFOLDER wget https://www.openssl.org/source/openssl-1.0.1g.tar.gz tar xzf openssl-1.0.1g.tar.gz cd openssl-1.0.1g ./config --prefix=/srv/www/vhosts/api/hhvm/ make make install ! ! ! !
tar -xzf onig-5.9.5.tar.gz cd onig-5.9.5 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! #ldap ! cd $SRCFOLDER wget ftp://sunsite.cnlab-switch.ch/mirror/OpenLDAP/openldap-release/openldap-2.4.38.tgz tar -xzf openldap-2.4.38.tgz cd openldap-2.4.38 ./configure --prefix=/srv/www/vhosts/api/hhvm/ --disable-slapd --disable-bdb make make install ! #libedit ! cd $SRCFOLDER wget http://thrysoee.dk/editline/libedit-20130712-3.1.tar.gz tar -xzf libedit-20130712-3.1.tar.gz cd libedit-20130712-3.1 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install ! #libelf ! cd $SRCFOLDER wget http://www.mr511.de/software/libelf-0.8.9.tar.gz tar -xzf libelf-0.8.9.tar.gz cd libelf-0.8.9 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make make install ! ! ! ! ! ! ! ! ! ! !
ftp://xmlsoft.org/libxslt/libxslt-1.1.28.tar.gz tar -xzf libxslt-1.1.28.tar.gz cd libxslt-1.1.28 ./configure --prefix=/srv/www/vhosts/api/hhvm make make install ! # imagick ! cd $SRCFOLDER wget http://mirror.checkdomain.de/imagemagick/ImageMagick-6.8.8-9.tar.gz tar -xf ImageMagick-6.8.8-9.tar.gz cd ImageMagick-6.8.8-9 make make install !
YES! - But of course it depends ! - Without JIT, it isn’t (in CLI for example) - JIT needs some warm up requests to find the hot paths - The more your scripts do, the more you gain.
servers of the Migros project - 16 CPU, 96 GB RAM, non virtualized - Symfony 2.4 as PHP Framework - Returns a JSON with product information - Retrieved from ElasticSearch (no SQL DB involved here) - Transformed with JMSSerializer ! - Tested with different concurrencies (2 - 80) - Tested against - PHP 5.3/apc with Apache Prefork - PHP 5.5/opcache with nginx - HHVM 3.0 with nginx
times faster than PHP 5.3 - HHVM is up to 2 times faster than PHP 5.5 - PHP 5.5 is up to 1.7 times faster than PHP 5.3 - HHVM scales a li!le bit be!er with concurrency - (load of server was also lower) - The longer your requests, the more you save ! ! - Others came to similar conclusions ;)
need to recompile HHVM with - cmake -D HOTPROFILER:BOOL=ON . - (it doesn’t have much performance impact) ! - You can use the usual xhprof tools ! - We also use New Relic with HHVM. See end of talk
//Typed properties (and scalar typehint) private int $num = 123; ! //Return typehints public function add(int $delta): Foo { $this->num += $delta; return $this; } ! public function get(): int { return $this->num; } ! // Constructor arg promotion public function __constructor(private int $num): void { } } ! //needed, typechecker doesn't check in global space function main() { ! $f = new Foo(123); $f->add(456); ! // gives error with hh_client $f->add("banana"); } ! main();
runs on linux right now, needs OCaml - hh_client spawns hh_server - hh_server watches file system on each save - makes hh_client really fast - doesn’t check with <?php ! - Integration for vim and emacs available, more should come
languages like C# or Java - Allow classes and methods to be parameterized <?hh ! class Value<T> { public function __construct(protected T $value) { } ! public function getValue(): T { return $this->value; } ! public function addString(string $bar) { } } ! function main2() { $st = new Value("TestString"); $st->addString($st->getValue()); ! $st = new Value(42); //errors out, since getValue returns int //$st->addString($st->getValue()); } ! main2();
ordered, index-based list) - Map (an ordered dictionary) - Set (a list of unique values) - Pair (an index-based collection of exactly two elements) - All also as Immutable classes - Clear interface - Literal syntax - It can be defined, what’s in those collections
to redeclare a type - Opaque Type aliasing restricts access to underlying implementation - Shapes are like struct in other languages, but for arrays - Helps in type checking <?hh ! //type alias type Point = (int, int); //opaque type alias newtype SecretID = int; //shape type Point2D = shape('x' => int, 'y' => int); ! function create_point(int $x, int $y): Point { return tuple($x, $y); } ! function dotProduct(Point2D $a, Point2D $b): int { return $a['x'] * $b['x'] + $a['y'] * $b['y']; }
SecretID = int; ! function modify_secret_id(SecretID $sid): SecretID { return $sid - time() - 2042; } ! function main_ot1(): void { echo modify_secret_id(44596); } ! main_ot1(); ! ! <?hh // File2.php ! require_once "opaquetypealiasing.php"; ! function try_modify_secret_id(SecretID $sid): SecretID { //gives an error, because it’s an operation on int return $sid + time() + 2000; } ! function main_ot2(): void { //gives an error, because it’s an int not a SecretID try_modify_secret_id(44596); } ! main_ot2();
multiple functions to run “simultaneously” - While one is blocking, the other executes - NOT threading - A li!le bit complicated right now, but more async native functions (database, scheduling, memory handling) will come <?hh // simplefied example, does not work this way, see next slide ! async function getPage($url) { $fp = fopen($url, 'r'); await $fp; return stream_get_contents($fp); } ! $pages = await [ getPage('http://php.net'), getPage('http://example.com'), getPage('http://hhvm.com'), ];
Argument Promotion http://docs.hhvm.com/manual/en/hack.constructorargumentpromotion.php //Vector http://docs.hhvm.com/manual/en/hack.collections.vector.php (instead of array) //Annotating Arrays and Collections: http://docs.hhvm.com/manual/en/hack.annotations.arrays.php public function __construct(private Vector<string> $urls) { $this->fetcher = new Fetcher(); } ! public async function run() : Awaitable<int> { ! //lambda expressions: http://docs.hhvm.com/manual/en/hack.lambda.php $waithandles = $this->urls->map($url ==> $this->fetcher->fetch($url)); ! // works too, but not supported by typechecker yet //$waithandles = $this->urls->map((string $url): Awaitable<int> ==> $this->fetcher->fetch($url)); // same as above, but with closure and annotations, so it catches type errors //$waithandles = $this->urls->map(function(string $url): Awaitable<int> {return $this->fetcher->fetch($url);}); ! //create wait handle for all and only continue when all have finished $x = await GenVectorWaitHandle::Create($waithandles); return $x->count(); } ! public function start() : string { return $this->run()->join() . " urls fetched and finished\n"; } } ! function main4() { //Vector with Literal Syntax: http://docs.hhvm.com/manual/en/hack.collections.literalsyntax.php $urls = Vector{"http://chregu.tv/webinc/sleep.php?s=1","http://chregu.tv/webinc/sleep.php?s=1"}; $f = new Fetch($urls); print $f->start(); } main4(); ! !
- User A!ributes (accessible via Reflection) - XHP – XHtml for PHP (Templating) - Continuations (like Generators in PHP) - Tuples (fixed size arrays) - Override A!ribute (define in a child class that there must be a parent class)
to PHP extensions anyway) - You can write the “easy” stuff in PHP/Hack - And switch to C++ for the harder stuff ! - We wrote an extension to use New Relic with HHVM - See blog.liip.ch/archive/2014/03/27/hhvm-and-new-relic.html for details
Doctrine DBAL only in dev branch) - Not really open dev model, Facebook controls it totally (and CLA needed for contribution), the far future is unknown - Still kind of moving target - Type Checker only really useful, when all your important classes are converted to <?hh - No easy way back, when you start using Hack. - If you need exotic extensions …
QUESTIONS? And some links: ! - The examples from this talk: github.com/chregu/hack-examples - The HHVM site: hhvm.com - with a blog: hhvm.com/blog - HHVM/Hack Docs: docs.hhvm.com - Hacklang site (with tutorial): hacklang.org