Appuyez sur [s] pour ouvrir les notes présentateur dans une nouvelle fenêtre.
Je vais essayer d'ajouter ici, pour certains slides, des points que j'ai pu donner à l'oral lors de la présentation et/ou qui ne sont pas explicitement écrits sur les slides — afin de les rendre plus utiles aux lecteurs qui n'auraient pas assisté à la présentation.
Le style sera volontairement un peu oral , se rapprochant un peu de ce qui s'est dit lors de la présentation live .
Facebook
Forte fréquentation
Performances ?
PHP
Au 21/05/2014, facebook.com est n°2 du top Alexa
PHP est là pour raisons historiques. Et si l'équipe de développement connait bien PHP (et sa stack), passer à une autre techno peut représenter un coût important.
Mélanger les technos (Extensions PHP en C, par exemple) ⇒ plus difficile pour les développeurs de l'équipe d'être à même de tous toucher à tout.
HipHop — HPHP
2009
Compilation PHP → C++ → Exécutable
Interpréteur (env. de dév.)
Mais…
Compilation longue, perte de souplesse
Production ≠ Développement, 2 projets à maintenir
1ère tentative de réponse à la problématique "performances"
Compilation du code PHP en code C++ lui-même ensuite compilé en un binaire
Binaire de + de 1GB = compliqué et long à mettre à jour (c'est pas du vim
directement sur un serveur (oui c'est mal ; mais des fois...))
HHVM
Mars 2013
Language : PHP
Compilation Just In Time
Serveur web intégré
Facebook : le site desktop tourne à 100% sous HHVM (en développement et en production ; donc un seul environnement d'exécution commun à dev et prod)
hhvm.com (blog officiel) sous Wordpress ; et sous HHVM
Support : Linux, Mac sans JIT, pas Windows pour l'instant
HHVM + Hack
Mars 2014
Languages : PHP et Hack
FastCGI
Performances = pas la seule question sur une grosse base de code
Une fois le côté "perfs" bien avancé, nécessité de bosser sur "le reste"
Industrialisation et qualité du code
Serveur : Apache ou nginx font bien le boulot. Donc ne pas réinventer la roue. Donc FastCGI.
HHVM
Compilation JIT
FastCGI (derrière nginx / Apache)
hhvm.com
Oui, je répête un peu ce que je disais en introduction
Installation
Cycle de releases
Internes : toutes les 2 semaines
Externes : toutes les 8 semaines
Nightly
Paquets pour les distributions les + utilisées
Ubuntu 10/12/14.04, Debian 7/8, Mint
Fedora 20, CentOS 6.x
Compilation depuis les sources
Développement / test nightly : vicb/hhvm-vagrant
Stack standard
Apache / nginx
HHVM en FastCGI
Base de données, stockage, …
FastCGI et Apache/nginx
Runtime options
HHVM derrière nginx : permet de servir un site via PHP en php-fpm, et un autre via HHVM ;-)
plein d'options de configuration ; cf la doc, pas tellement utile de les lister ici
Utilisation et compatibilité
HHVM et site simple
Exécutable hhvm
en CLI
Compatibilité Logiciels et Frameworks
Composer, Doctrine2, guzzle, monolog, twig : 100%
zf2, symfony, laravel : 97-100%
phpbb3, phpMyAdmin, mediawiki : 100%
HHVM en CLI : moins de gain sur le JIT ; pas forcément intéressant pour des scripts courts.
Effort fait pour supporter au mieux pas mal de frameworks ; ne peut qu'aider à l'adoption.
Extensibilité
Extension PHP intégrées : curl
, dom
, json
, ldap
, memcached
, mysql
, pdo
, phar
, soap
, spl
, …
Extensions externes : geoip
, mongo
, pgsql
, …
Code PHP intégré à HHVM après re-compilation
Extensions écrites en C++
Performances
Faites le test sur vos applications !
HHVM peut être 4 à 6 fois plus rapide que PHP.
Pas mal de benchmarks dispo sur le net ⇒ pas tellement intéressant d'en refaire un, surtout qu'un bench n'est jamais 100% représentatif de la réalité.
Beaucoup de calculs en PHP ? JIT a besoin de quelques requêtes pour démarrer. CLI pas tellement avantagé.
Symfony benchmark using HHVM ,
HHVM with Symfony 2 looks amazing
Hack ?
But = faire tourner une appli PHP.
Et ensuite y ajouter des points spécifiques à Hack.
En gros, Hack = PHP + typage statique + quelques features - quelques trucs pas trop utilisés
Mais pourquoi ?
Ajout de fonctionnalités
Qualité ↗
Risque d'erreurs ↘
Compatibilité avec PHP
Conservation du principe de développement facile en PHP, avec points de discipline , notamment avec le typage statique.
Facilitation du refactoring (là où aujourd'hui les IDE PHP se basent beaucoup sur les commentaires phpdoc).
Coder en Hack
Balise <?hh
en début de fichier
Éventuellement : extension .hh
Marqueur ?>
non supporté !
Pas de mélange Hack/HTML !
<?hh
echo "Hello, Hack !";
On ne peut pas écrire ceci :
Un peu de HTML
<?hh
echo "Hello, Hack !";
?>
Et encore du HTML
Un fichier qui contient <?hh
ne doit contenir que du Hack. Langage de programmation et pas de templating
Typage
Type de retour fonctions / méthodes
Type pour les variables membres
Types nullables
Collections type-safe
Outil de vérification de types
Détection avant l'exécution, code + explicite
Types de retour
Fonctions, Méthodes
<?hh
function ma_fonction() : int {
return "une chaine";
}
var_dump(ma_fonction());
Fatal error: Value returned from ma_fonction()
must be of type int,
string given in /…/types-01.php on line 4
Historiquement en PHP : typage via phpdoc ; mais rien ne garantissant qu'elle soit juste, puisque pas de type-checking
Ici, on a déclaré qu'on retournait un int
, alors que le code retourne en fait une string
; donc erreur
Il y a une RFC pour ajouter à PHP le typage du retour : Return Type Declarations
Typage de paramètres
Étendu aux types scalaires
<?hh
class MaClasse {
public static function test(string $str, int $entier) {
return sprintf("%s, %d", $str, $entier);
}
}
var_dump(MaClasse::test("Hello", 42));
Premier paramètre de type string
Et second de type int
Types nullable
Valeur doit être du type spécifié,
ou null
A n'utiliser que quand c'est justifié
<?hh
function ma_fonction(string $str, ?int $a) {
echo $str;
if (null !== $a) {
echo " " . $a;
}
}
ma_fonction("Hello", null);
ma_fonction("Hello", 42);
Syntaxe : ?
suivi du type
Par exemple, pour le retour, null
peut correspondre à un cas d'erreur.
Correspond bien à NULL
en base de données quand une colonne n'a pas encore de valeur.
Ne signifie pas que le paramètre est optionnel ; mais qu'il peut valoir null
Quels types ?
Types primitifs : int
, float
, string
, bool
Classes : MaClasse
, Vector<type>
, this
Mixed : mixed
Void : void
Cf plus loin pour plus de détails sur certains de ces types
Quels types ?
Nullable : ?int
Tableaux : array
, array<int>
, array<MaClasse>
, array<int, MaClasse>
Closures : function(string, int): bool
Tuples, éléments XHP, Generics et resource
Type Checker
Fichier .hhconfig
à la racine du projet
Type checker fonctionne en arrière-plan
hh_client
affiche son état
$ hh_client
/…/types-01.php:4:12,23: Invalid return type
/…/types-01.php:3:26,28: This is an int
/…/types-01.php:4:12,23: It is incompatible with a string
Plugins pour vim et emacs.
Possibilité d'en développer pour d'autres IDE.
Generics
Type d'une classe est paramétré
Permet la vérification statique
Code lisible et explicite
<?hh
class MaClasse<T> {
protected T $data;
public function __construct(T $data) {
$this->data = $data;
}
public function getData() : T {
return $this->data;
}
}
$a = new MaClasse("plop");
var_dump($a->getData());
Reprend l'idée (et à peu de chose près la syntaxe) des templates de C++ ou des Generics de Java
Checks statiques, plutôt que de se baser sur des instanceof
partout
Note : new MaClasse("plop")
ou new MaClasse<string>("plop")
Generics
Classe ou méthode générique
MaClasse<string>
et MaClasse<int>
= deux types différents
Traits et interfaces peuvent être génériques
Contraintes
Type doit être un (sous-)type donné
class MaClasse<T as Iterator>
Collections
array
de PHP : dictionnaires, ordre d'insertion conservé, clefs int/string, contenu de n'importe quel type
Collections de Hack : paramétrées (generics), spécifiques aux cas d'usages, objets
Vector
, Map
, Set
, Pair
+ version Imm
utable des 3 premières
Objectifs : code explicite, typage statique, performances
Usage assez proche de ce à quoi les développeurs PHP sont habitués
Et suivent les design patterns familiers aux développeurs C++, C#, Java, Python, …
Syntaxe litérale : Vector {"plop", "glop"}
Une partie des fonctions reprises de PHP sait travailler sur des collections
Collections : Vector
// Pas de 'new' !
$vector = Vector {10, 20};
$vector[] = 30;
$vector[] = 40;
// Accès direct avec [indice]
printf("\$vector[2] = %d\n", $vector[2]);
// Suppression d'un élément
$vector->removeKey(2);
// Itération avec foreach()
foreach ($vector as $key => $value) {
printf("%d => %d\n", $key, $value);
}
Accès à une clef inexistante ⇒ OutOfBoundsException
On peut avoir des méthodes sur une collection, alors qu'on ne peut pas en avoir sur array
Collections
Map
Dictionnaire clef (int
ou string
) /valeur
Ordonné
Set
Stockage de valeurs (int
ou string
) uniques
Pas de clef !
ImmVector
, ImmMap
, ImmSet
Interfaces Const*
Interfaces Const*
: en paramètre d'une fonction, pour indiquer qu'elle ne modifie pas la collection
Et les array
alors ?
Recommandation : Collections
array
existent toujours
array
array<UnType>
array<int, UnType>
et array<string, UnType>
array<T>
, array<int, Tv>
, array<string, Tv>
Doivent être typés en mode strict
Shapes
Notion de structure ou d'enregistrement
Avec type-checking
Assimilable à une classe n'ayant que des propriétés, publiques
<?hh
type Point = shape('x' => int, 'y' => int);
function display_point(Point $p) {
printf("%d ; %d", $p['x'], $p['y']);
}
display_point( shape('x' => 10, 'y' => -2) );
En PHP, on utilise souvent des array
… Sans type-checking, donc
Tuple
<?hh
function ma_fonction(int $a, int $b) : (int, int) {
return tuple($a*2, $b*2);
}
$result = ma_fonction(10, 20);
var_dump($result);
array(2) {
[0]=> int(20)
[1]=> int(40)
}
Couple de données
Non modifiable
Lambda
PHP
Binding de variables non-automatique : use(...)
Syntaxe un peu verbeuse
Hack
Capture automatique
Syntaxe + courte
Opérateur ==>
Lambda
<?hh
$func = ($a, $b) ==> {
return $a . " " . $b;
};
var_dump( $func("hello", "world") );
$result = array_map(
$val ==> strtoupper($val),
["un", "deux", "trois", ]
);
var_dump($result);
1er cas, déclaration d'une fonction anonyme $func
puis appel
2nd cas, passage en paramètre de la lambda directe à array_map()
Syntaxe (un peu ?) plus courte que PHP... Mais est-elle vraiment plus lisible ?
Lambda
<?hh
for ( $i = 1 ; $i < 5 ; $i++ ) {
$func = $val ==> {
// $i est automatiquement capturé
return $i * $val;
};
var_dump(array_map(
$func,
[10, 20, 30, 40, 50]
));
}
Variables automatiquement capturées : pas de use()
Syntaxe plus courte, donc... Mais en même temps moins safe ?
Lambda
Type-hinting (parametres, retours) non supporté par le type-checker
Pas de valeurs par défaut
Pas de paramètre / retour par référence
Async
Parallélisation de tâches, en isolation
Exemple : I/O
Fonction asynchrone
Mots-clef : async
et await
async
déclare une fonction comme asynchrone
await
suspend l'exécution d'une fonction asynchrone jusqu'à ce que le résultat de l'opération asynchrone représentée par await
soit disponible
Async
Pas encore tout à fait évident
<?hh
async function helloAfter($name, $timeout) {
// sleep asynchronously -- let other async functions do their job
await SleepWaitHandle::create($timeout * 1000000);
echo sprintf("hello %s\n", $name);
}
async function run() {
$joe = helloAfter('Joe', 3);
$mike = helloAfter('Mike', 1);
// wait for both dependencies
await GenArrayWaitHandle::create(array($joe, $mike));
}
run()->join();
Source : asio
Voir aussi : async_fetcher.php (100 lignes)
En cherchant un peu sur Internet, vous trouverez un exemple long de téléchargement en parallèle de plusieurs URLs. En voyant ça, y'a encore du progrès à faire avant que async soit réellement accessible !
Async
Support basique pour l'instant
Travail en cours !
TODO : appels bases de données, gestion de mémoire, scheduling, …
J'insiste : travail en cours ; c'est aussi noté en gros rouge dans le manuel ^^
Il reste des choses à mettre en place avant que ce soit réellement utile
Quatre modes
partial
: par défaut
strict
: tout doit être annoté, pas d'appel à du non-Hack, pas de code top-level
decl
: permet des appels non-Hack
unsafe
: désactive le type-checking
<?hh // strict
// Ici, du code Hack (strict)
Strict : toutes les erreurs de type sont remontées, tout doit être annoté (pas d'array
non typés !), impossible d'appeler du code non-Hack.
Partial : mode par défaut. Possible de typer seulement une partie d'une classe/méthode/fonction et d'appeler du code non-Hack.
decl
: parmet d'avoir du code non-strict appelable depuis du code strict.
// UNSAFE
désactive le type-checker de là où l'instruction figure jusqu'à la fin du bloc courant.
Et encore ?
Annotation <<Override>>
Aliasing de types
XHP
Promotion des arguments du constructeur
<?hh
class Point {
// $x et $y ne sont pas déclarés…
public function __construct(
protected int $x,
protected int $y
) {
// … ni assignés
}
}
Override : une erreur est levée si cet attribut est présent sur une méthode non-définie dans la classe parente
Continuation<T>
Outillage : profiler inclu (il peut falloir recompiler), debugger (style gdb) avec breakpoints/watches/macros
Promotion des arguments du constructeur : un peu surprenant (alors que Hack introduit du typage strict) qu'il ne soit pas nécessaire de déclarer les propriétés
Il y a eu une RFC pour faire un peu pareil en PHP
Non supporté
goto
, syntaxe if: … endif;
, and
/or
Opérateur @
break N
et continue N
Variables globales
Mélange HTML/Hack
Méthode du nom de la classe
PHP et Hack
Pas forcément le plus facile ou le plus fun
Implémentation historique
Un langage, plusieurs publics
Performances ≠ besoin 1er de la majorité
Coût / risque de migration
PHP 5.3 : 51.8%
PHP 5.2 : 27.2%
PHP 5.4 : 17.3%
PHP 5.5 : 2.1%
Chiffres w3techs.com
PHP 5.5 a un an... Et seulement 2% ;-(
Si la moitié des installations de PHP sont encore en PHP 5.3, ce n'est pas demain la veille qu'elles seront sous HHVM/Hack à jour
Certes : HHVM/Hack n'est peut-être pas encore pour le grand-public ?
Ouverture à la communauté
Fortement soutenu par une entreprise
Open-Source, volonté d'ouverture
PR Github
Compatibilité frameworks et logiciels
Bon accueil
Implémentations alternatives
Implémentations alternatives
Concurrence : faire avancer PHP
Risque de fractionnement
Evolution de chaque implémentation indépendamment des autres
Scripts / applis / bibliothèques ne fonctionnant que sous un moteur ou l'autre
A propos de concurrence, on peut parler de RFCs
Typage du retour d'une fonction
Promotion des arguments du constructeur
Generics discutés plusieurs fois, notamment au moment de arrayof
PHPTour
23 et 24 juin 2014, Lyon
Benjamin Clay et Mathieu Darse donneront une conférence intitulée "HHVM et 'Hack', prenez 2 versions d'avance sur PHP" au PHPTour, les 23 et 24 juin 2014 à Lyon.
Photo par vapourtrails sur Flickr, CC-BY-NC-SA.