Slide 1

Slide 1 text

Agile Web Development Liip.ch ! – Zürich, 2014 HIPHOP VIRTUAL MACHINE (HHVM) FOR PHP AND THE HACK LANGUAGE Webtuesday, 8. April 2014

Slide 2

Slide 2 text

AGENDA - HHVM - The Engine - Hack - The Language ! - If you have questions during the talk, just ask (or at the end)

Slide 3

Slide 3 text

ABOUT ME AND WHY I TALK ABOUT HHVM - Partner 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

Slide 4

Slide 4 text

HHVM - WHAT IS IT - HHVM = HipHop Virtual 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

Slide 5

Slide 5 text

HHVM - THE (SHORT) HISTORY - In 2008, Facebook startet 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

Slide 6

Slide 6 text

HHVM - TODAY - Drop in replacement for PHP-FPM via 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)

Slide 7

Slide 7 text

HHVM - INSTALLATION - DEBIAN deb http://dl.hhvm.com/ubuntu saucy main apt-get update apt-get install hhvm /etc/init.d/hhvm start ! and in nginx config ! location ~ \.php$ {! fastcgi_pass 127.0.0.1:9000;! fastcgi_index index.php;! fastcgi_param SCRIPT_FILENAME! /var/www$fastcgi_script_name;! include fastcgi_param;! }

Slide 8

Slide 8 text

HHVM - INSTALLATION - SUSE # this is needed for 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 ! ! ! !

Slide 9

Slide 9 text

HHVM - INSTALLATION - SUSE #isl ! cd $SRCFOLDER wget 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 ! ! !

Slide 10

Slide 10 text

HHVM - INSTALLATION - SUSE #libevent ! cd $SRCFOLDER wget 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 ! ! ! ! ! !

Slide 11

Slide 11 text

HHVM - INSTALLATION - SUSE #libmemcached (1.0.17 doesn't work) ! 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 .. ! ! ! ! !

Slide 12

Slide 12 text

HHVM - INSTALLATION - SUSE #gd ! cd $SRCFOLDER wget 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 ! ! ! !

Slide 13

Slide 13 text

HHVM - INSTALLATION - SUSE #oniguruma ! cd $SRCFOLDER http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.5.tar.gz 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 ! ! ! ! ! ! ! ! ! ! !

Slide 14

Slide 14 text

HHVM - INSTALLATION - SUSE #dwarf ! cd $SRCFOLDER wget http://gentoo.skyfms.com/distfiles/libdwarf-20120410.tar.gz cd dwarf-20120410/libdwarf ./configure --prefix=/srv/www/vhosts/api/hhvm/ --enable-shared make cp libdwarf/libdwarf.a /srv/www/vhosts/api/hhvm/lib64/ cp libdwarf/libdwarf.h /srv/www/vhosts/api/hhvm/include/ cp libdwarf/dwarf.h /srv/www/vhosts/api/hhvm/include/ ! #cclient ! cd $SRCFOLDER wget ftp://ftp.cac.washington.edu/imap/imap-2007f.tar.gz cd imap-2007f make slx SSLTYPE=none cp -r c-client ../../include/ cp -r c-client/c-client.a ../../lib/libc-client4.a ! #attr ! cd $SRCFOLDER wget http://download.savannah.gnu.org/releases-noredirect/attr/attr-2.4.46.src.tar.gz tar -xzf attr-2.4.46.src.tar.gz cd attr-2.4.46 ./configure --prefix=/srv/www/vhosts/api/hhvm/ make install cp libattr/.libs/libattr.so ../../lib/ ! #libcap cd $SRCFOLDER wget ftp://ftp.de.debian.org/debian/pool/main/libc/libcap2/libcap2_2.22.orig.tar.gz tar -xzf libcap2_2.22.orig.tar.gz cd libcap-2.22/ export prefix=/srv/www/vhosts/api/hhvm/lib export LDFLAGS="-L /srv/www/vhosts/api/hhvm/lib" make make install ! #binutils ! cd $SRCFOLDER wget http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.bz2 tar -xjf binutils-2.24.tar.bz2 cd binutils-2.24 ./configure —prefix=/srv/www/vhosts/api/hhvm ! !

Slide 15

Slide 15 text

HHVM - INSTALLATION - SUSE #libxslt ! cd $SRCFOLDER wget 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 !

Slide 16

Slide 16 text

HHVM - INSTALLATION - SUSE # since hhvm 3.0 we switched to fastcgi via nginx # nginx ! cd $SRCFOLDER wget http://nginx.org/download/nginx-1.4.7.tar.gz tar -xzf nginx-1.4.7.tar.gz cd nginx-1.4.7 ./configure --prefix=/srv/www/vhosts/api/hhvm --http-log-path=/srv/www/vhosts/api/shared/app/logs/nginx-access.log --error-log-path=/srv/www/vhosts/api/shar nginx-error.log --conf-path=/srv/www/vhosts/api/hhvm/etc/nginx/nginx.conf --pid-path=/srv/www/vhosts/api/pids/nginx.pid --http-fastcgi-temp-path=/srv/www/vh mkdir /srv/www/vhosts/api/hhvm/etc/nginx/ make make install ! # INSTALL all the depend ! #hhvm ! cd $SRCFOLDER git clone https://github.com/facebook/hhvm.git cd hhvm git submodule init git submodule update export HPHP_HOME=`/bin/pwd` ./configure -DCMAKE_PREFIX_PATH=/srv/www/vhosts/api/hhvm/ \ -DCMAKE_C_COMPILER=/srv/www/vhosts/api/hhvm/bin/gcc \ -DCMAKE_INCLUDE_PATH=/srv/www/vhosts/api/hhvm/include \ -DCMAKE_INSTALL_PREFIX=/srv/www/vhosts/api/hhvm/ \ -DLIBMAGICKWAND_INCLUDE_DIRS=/srv/www/vhosts/api/hhvm/include/ImageMagick-6 \ -DLIBMAGICKWAND_LIBRARIES=/srv/www/vhosts/api/hhvm/lib/libMagickWand-6.Q16.so # evt. noch # cmake -D HOTPROFILER:BOOL=ON . make install

Slide 17

Slide 17 text

HHVM - INSTALLATION - SUSE PHEEEEW … (Maybe not everything was actually needed to built from source and SuSE would have provided it, but we were not the sysadmins ;))

Slide 18

Slide 18 text

HHVM - PERFORMANCE - Is it actually much faster? - 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.

Slide 19

Slide 19 text

HHVM - PERFORMANCE TESTS - Done with siege on the 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

Slide 20

Slide 20 text

HHVM - SOME CHARTS Get 1 Product from the API (a small request) requests per second 0 20 40 60 80 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0 ms per request 0 450 900 1350 1800 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0

Slide 21

Slide 21 text

HHVM - SOME CHARTS Get 16 products from the API (a medium request) requests per second 0 13 26 39 52 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0 ms per request 0 1000 2000 3000 4000 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0

Slide 22

Slide 22 text

HHVM - SOME CHARTS Get 50 products from the API (a large request) requests per second 0 7 14 21 28 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0 ms per request 0 2250 4500 6750 9000 2 4 6 10 20 40 80 PHP 5.3/apache PHP 5.5/fpm HHVM 3.0

Slide 23

Slide 23 text

HHVM - PERFORMANCE SUMMARY - HHVM is up to 3.5 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 ;)

Slide 24

Slide 24 text

HHVM - PROFILING - xhprof is included - But you 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

Slide 25

Slide 25 text

HHVM - DEBUGGING - With HPHPd - HPHP Debugger - Interactive shell -  GDB-like debugging -  Standalone or w/ server -  Breakpoints -  Watches -  Macros

Slide 26

Slide 26 text

THE HACK LANGUAGE PHP on Steroids

Slide 27

Slide 27 text

HACK - TYPE HINTING - Scalars - bool, int, float, num, string - Return typehints - Typed properties - Constructor arg promotion ! - Static analyzer (hh_client/hh_server) looks for mismatches and errors without running code

Slide 28

Slide 28 text

HACK - TYPE HINTING 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();

Slide 29

Slide 29 text

HACK - TYPE CHECKER - hh_client / hh_server - Only 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

Slide 30

Slide 30 text

HACK - GENERICS - You may know them from other languages like C# or Java - Allow classes and methods to be parameterized { 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();

Slide 31

Slide 31 text

HACK - COLLECTIONS - Specialized array objects - Vector (an 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

Slide 32

Slide 32 text

HACK - COLLECTIONS $nums, Set $names, Map $numNameMap, ImmVector $nums2): bool { ! foreach($nums as $num) { $mappedName = $numNameMap[$num]; if ($names->contains($mappedName)) { return true; } } if ($nums2->count() == 0) return true; return false; } ! function main3() { $vector = Vector {1, 2, 3}; $set = Set {"foo", "bar", "baz"}; $map = Map { 1 => "hello", 2 => "world" , 3 => "baz"}; $frozen = ImmVector{5,6}; var_dump(CollectionDemo($vector, $set, $map, $frozen)); } ! main3(); !

Slide 33

Slide 33 text

HACK - TYPE ALIASING AND SHAPES - Type aliasing allows 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 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']; }

Slide 34

Slide 34 text

HACK - OPAQUE TYPE ALIASING

Slide 35

Slide 35 text

HACK - LAMBDA EXPRESSION - Like closures, but shorter - Implicitly captures variables from outer scope $x + 1; $foo(12); // returns 13 ! $foo = () ==> 73; $foo(); // returns 73 ! $bar = ($x,$y) ==> $x + $y; $bar(3,8); // returns 11 ! //type hints (not supported yet by the typechecker, gives an error) $captured = "test: "; $bar = (string $k = "foo"): string ==> $captured . $k; !

Slide 36

Slide 36 text

HACK - ASYNC OPERATIONS - Parallelizing made “easy” - Allow 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

Slide 37

Slide 37 text

HACK - ASYNC OPERATIONS { $ch1 = curl_init(); print "get $url \n"; ! curl_setopt($ch1, CURLOPT_URL, $url); curl_setopt($ch1, CURLOPT_HEADER, 0); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); ! $mh = curl_multi_init(); curl_multi_add_handle($mh,$ch1); ! $active = null; do { $mrc = curl_multi_exec($mh, $active); // reschedule it for async to work properly await RescheduleWaitHandle::Create(1, 1); } while ($mrc == CURLM_CALL_MULTI_PERFORM); ! while ($active && $mrc == CURLM_OK) { if (curl_multi_select($mh) != -1) { do { $mrc = curl_multi_exec($mh, $active); await RescheduleWaitHandle::Create(1, 1); // simulate blocking I/O } while ($mrc == CURLM_CALL_MULTI_PERFORM); } } print "finished $url\n"; return 1; } } !

Slide 38

Slide 38 text

! class Fetch { ! protected Fetcher $fetcher; ! //Constructor 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 $urls) { $this->fetcher = new Fetcher(); } ! public async function run() : Awaitable { ! //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 ==> $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 {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(); ! !

Slide 39

Slide 39 text

HACK - FURTHER FEATURES - Nullable Types. ?int, ?string, ?class - 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)

Slide 40

Slide 40 text

HHVM - WRITING EXTENSIONS - It’s not that hard (compared 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

Slide 41

Slide 41 text

HHVM - WRITING EXTENSIONS getMessage(); } $exception_type = get_class($e); $stack_trace = $e->getTraceAsString(); } else { $exception_type = ""; $stack_trace = NewRelicExtensionHelper::debug_backtrace_string(); } $stack_frame_delimiter = "\n"; newrelic_notice_error_intern( $exception_type, $error_message, $stack_trace, $stack_frame_delimiter); } function newrelic_start_transaction(string $appname, string $license = null) { newrelic_start_transaction_intern(); newrelic_transaction_set_request_url($_SERVER["REQUEST_URI"]); } ! //... ! <<__Native>> function newrelic_start_transaction_intern(): int; ! <<__Native>> function newrelic_name_transaction_intern(string $name): int; ! <<__Native>> function newrelic_transaction_set_request_url(string $name): int; ! <<__Native>> function newrelic_transaction_set_threshold(int $threshold): int; !

Slide 42

Slide 42 text

// newrelic.cpp #include "hphp/runtime/base/base-includes.h" #include "hphp/runtime/ext/ext_error.h" #include "newrelic_transaction.h" #include "newrelic_collector_client.h" #include "newrelic_common.h" //... using namespace std; namespace HPHP { bool keep_running = true; static int64_t HHVM_FUNCTION(newrelic_start_transaction_intern) { long transaction_id = newrelic_transaction_begin(); return transaction_id; } static int HHVM_FUNCTION(newrelic_name_transaction_intern, const String & name) { return newrelic_transaction_set_name(NEWRELIC_AUTOSCOPE, name.c_str()); } static int HHVM_FUNCTION(newrelic_transaction_set_request_url, const String & request_url) { return newrelic_transaction_set_request_url(NEWRELIC_AUTOSCOPE, request_url.c_str()); } //... static class NewRelicExtension : public Extension { public: NewRelicExtension () : Extension("newrelic") { config_loaded = false; } virtual void init_newrelic() { newrelic_register_message_handler(newrelic_message_handler); newrelic_init(license_key.c_str(), app_name.c_str(), app_language.c_str(), app_language_version.c_str()); } virtual void moduleLoad(Hdf config) { if (!config.exists("EnvVariables")) return; Hdf env_vars = config["EnvVariables"]; //... } virtual void moduleInit () { if (config_loaded) init_newrelic(); ! HHVM_FE(newrelic_start_transaction_intern); HHVM_FE(newrelic_name_transaction_intern); HHVM_FE(newrelic_transaction_set_request_url); //... loadSystemlib(); } virtual void requestShutdown() { newrelic_transaction_end(NEWRELIC_AUTOSCOPE); } virtual void requestInit() { f_set_error_handler(s__NR_ERROR_CALLBACK); f_set_exception_handler(s__NR_EXCEPTION_CALLBACK); //TODO: make it possible to disable that via ini GlobalVariables *g = get_global_variables(); newrelic_transaction_begin(); String request_url = g->get(s__SERVER).toArray()[s__REQUEST_URI].toString(); newrelic_transaction_set_request_url(NEWRELIC_AUTOSCOPE, request_url.c_str()); String script_name = g->get(s__SERVER).toArray()[s__SCRIPT_NAME].toString(); newrelic_transaction_set_name(NEWRELIC_AUTOSCOPE, script_name.c_str()); } } s_newrelic_extension; HHVM_GET_MODULE(newrelic) } // namespace HPHP

Slide 43

Slide 43 text

HHVM - DRAWBACKS? - Not every library works yet (eg. 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

Slide 44

Slide 44 text

Agile Web Development Liip.ch ! – Christian Stocker @chregu [email protected] 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