La programmation asynchrone... et les pates

73
LA PROGRAMMATION ASYNCHRONE ET LES PÂTES François Zaninotto - @francoisz - marmelab.com

description

La vidéo de la conférence au Forum PHP 2013 / AFUP : https://www.youtube.com/watch?v=WygFJHEloq0

Transcript of La programmation asynchrone... et les pates

Page 1: La programmation asynchrone... et les pates

LA PROGRAMMATION ASYNCHRONE ET LES PÂTES

François Zaninotto - @francoisz - marmelab.com

Page 2: La programmation asynchrone... et les pates

PARLONS

CUISINE

Page 3: La programmation asynchrone... et les pates

Pour 4 personnes Préparation et cuisson: 20 minutes Ingrédients: - 500g de spaghetti - 6 tomates bien mûres - 1 oignon - 1 carotte - 2 gousses d'ail - 1 branche de céleri - huile d'olive - sauge, romarin, basilic frais - sel et poivre - amour

Spaghetti à la tomate de Giuseppina Plat principal - Facile - Bon marché

Page 4: La programmation asynchrone... et les pates

1. Faire bouillir une grande quantité d'eau (non salée) dans une casserole

2. Pendant ce temps, pelez les tomates et coupez-les grossièrement

3. Epluchez et émincez l'oignon, la carotte, l'ail et le céleri

4. Lorsque l'eau bout, salez-la, puis déposez les spaghettis en couronne

5. Faire chauffer l'huile d'olive dans une sauteuse. Mettez-y à brunir la deuxième gousse d'ail préalablement épluchée.

6. Retirez la gousse d'ail, puis versez le mirepoix (mélange de légumes) et faites revenir à feu vif

7. Ajoutez les tomates, les herbes, salez et poivrez copieusement. Faites chauffer à feu moyen pendant 5 minutes

8. Goûtez régulièrement les spaghettis. Lorsqu'ils sont cuits al dente, égouttez-les puis déposez-les dans un plat chaud.

9. Versez la sauce tomate immédiatement sur les pâtes fumantes. Ajoutez le basilic grossièrement découpé.

10.Servez avec du parmesan rapé et un bon Chianti Classico, et régalez-vous

Spaghetti à la tomate de Giuseppina Plat principal - Facile - Bon marché

Page 5: La programmation asynchrone... et les pates

MAINTENANT LE CHEF C’EST

PHP

Page 6: La programmation asynchrone... et les pates

//  time  is  0  $pastaPan  =  new  Pan();  $water  =  new  Water();  $pastaPan-­‐>fill($water);  $pastaPan-­‐>warm($duration  =  10);  //  now  time  is  10  $pastaPan-­‐>fill(new  Spaghetti());  $pastaPan-­‐>warm($duration  =  8);  //  now  time  is  18  $pastaPan-­‐>remove($water);  !$saucePan  =  new  Pan();  $saucePan-­‐>fill(new  OliveOil());  $saucePan-­‐>warm($duration  =  2);  //  now  time  is  20  $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));  $saucePan-­‐>warm($duration  =  5);  //  now  time  is  25  $saucePan-­‐>fill(TomatoFactory::create());  $saucepan-­‐>warm($duration  =  4);  //  now  time  is  29  !$plate  =  new  Plate();  $plate-­‐>addContentsOf($pastaPan);  $plate-­‐>addContentsOf($saucePan);  $plate-­‐>serve('Régalez-­‐vous');

Page 7: La programmation asynchrone... et les pates

LES 3 GRANDS TABOUS DU DEVELOPPEUR

UTILISER eval()

Page 8: La programmation asynchrone... et les pates

INJECTER UN CONTENEUR D’INJECTION DE DÉPENDANCE

LES 3 GRANDS TABOUS DU DEVELOPPEUR

Page 9: La programmation asynchrone... et les pates

SERVIR DES PÂTES FROIDES

LES 3 GRANDS TABOUS DU DEVELOPPEUR

Page 10: La programmation asynchrone... et les pates

2/10 NOTE DES INVITÉS

Page 11: La programmation asynchrone... et les pates

EVENTLOOP À LA RESCOUSSE

Page 12: La programmation asynchrone... et les pates

class  EventLoop  {      protected  $tick  =  0;      protected  $callbacksForTick  =  array();  !    public  function  executeLater($delay,  $callback)  {          $this-­‐>callbacksForTick[$this-­‐>tick  +  $delay]  []=  $callback;      }          public  function  start()  {          while  ($this-­‐>callbacksForTick)  {              $this-­‐>tick++;              $this-­‐>executeCallbacks();          }      }            public  function  executeCallbacks()  {          echo  "tic-­‐tac  :  "  .  $this-­‐>tick  .  "\n";          if  (!isset($this-­‐>callbacksForTick[$this-­‐>tick]))  {              return;  //  no  callback  to  execute          }          foreach  ($this-­‐>callbacksForTick[$this-­‐>tick]  as  $callback)  {              call_user_func($callback);          }          //  clean  up          unset($this-­‐>callbacksForTick[$this-­‐>tick]);      }  }

Page 13: La programmation asynchrone... et les pates

LA CASSEROLE

ASYNCHRONE

Page 14: La programmation asynchrone... et les pates

class  AsynchronousPan  extends  Pan  {      protected  $eventLoop;            public  function  __construct(EventLoop  $eventLoop)      {          $this-­‐>eventLoop  =  $eventLoop;      }            public  function  warm($duration,  $callback)      {          $this-­‐>eventLoop-­‐>executeLater($duration,  $callback);      }  }

Page 15: La programmation asynchrone... et les pates

$eventLoop  =  new  EventLoop();  !

$pan  =  new  AsynchronousPan($eventLoop);  $pan-­‐>warm(10,  function()  {      echo  "Régalez-­‐vous\n";  });  !

echo  "Ca  chauffe  !\n";  !

$eventLoop-­‐>start();

Page 16: La programmation asynchrone... et les pates

DÉMONSTRATION

Page 17: La programmation asynchrone... et les pates

Ca  chauffe  !  tic-­‐tac  :  1  tic-­‐tac  :  2  tic-­‐tac  :  3  tic-­‐tac  :  4  tic-­‐tac  :  5  tic-­‐tac  :  6  tic-­‐tac  :  7  tic-­‐tac  :  8  tic-­‐tac  :  9  tic-­‐tac  :  10  Régalez-­‐vous

Page 18: La programmation asynchrone... et les pates

LES SPAGHETTI

ASYNCHRONES

Page 19: La programmation asynchrone... et les pates

$eventLoop  =  new  EventLoop();  !

$plate  =  new  Plate();  !

//  pasta  $pastaPan  =  new  AsynchronousPan($eventLoop);  $water  =  new  Water();  $pastaPan-­‐>fill($water);  echo  "pastaPan:  Allumage\n";  $pastaPan-­‐>warm($duration  =  10,  function()  use  ($pastaPan,  $plate,  $water)  {      echo  "pastaPan:  L'eau  bout\n";      $pastaPan-­‐>fill(new  Spaghetti());      echo  "pastaPan:  Lancement  de  la  cuisson  des  spaghettis\n";      $pastaPan-­‐>warm($duration  =  8,  function()  use  ($pastaPan,  $plate,  $water){          echo  "pastaPan:  Les  spaghettis  sont  prêts\n";          $pastaPan-­‐>remove($water);          $plate-­‐>addContentsOf($pastaPan);      });  });  ../..

Page 20: La programmation asynchrone... et les pates

../..  //  sauce  $eventLoop-­‐>executeLater($delay  =  7,  function()  use  ($plate,  $eventLoop)  {      $saucePan  =  new  AsynchronousPan($eventLoop);      $saucePan-­‐>fill(new  OliveOil());      echo  "saucePan:  L'huile  chauffe\n";      $saucePan-­‐>warm($duration  =  2,  function()  use($saucePan,  $plate)  {          echo  "saucePan:  L'huile  est  chaude\n";          $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));          echo  "saucePan:  Lancement  de  la  cuisson  du  mirepoix\n";          $saucePan-­‐>warm($duration  =  5,  function()  use($saucePan,  $plate)  {              echo  "saucePan:  Le  mirepoix  est  prêt  pour  la  tomate\n";              $saucePan-­‐>fill(TomatoFactory::create());              echo  "saucePan:  Lancement  de  la  cuisson  de  la  tomate\n";              $saucePan-­‐>warm($duration  =  4,  function()  use($saucePan,  $plate)  {                  echo  "saucePan:  La  sauce  est  prête\n";                  $plate-­‐>addContentsOf($saucePan);              });          });      });  });  !$eventLoop-­‐>start();  $plate-­‐>serve('Régalez-­‐vous');

Page 21: La programmation asynchrone... et les pates

SÉQUENTIALITÉSy

nchro

ne

Asynchrone

Page 22: La programmation asynchrone... et les pates

pastaPan:  Allumage  tic-­‐tac  :  1  ...  tic-­‐tac  :  7  saucePan:  L'huile  chauffe  tic-­‐tac  :  8  tic-­‐tac  :  9  saucePan:  L'huile  est  chaude  saucePan:  Lancement  de  la  cuisson  du  mirepoix  tic-­‐tac  :  10  pastaPan:  L'eau  bout  pastaPan:  Lancement  de  la  cuisson  des  spaghettis  tic-­‐tac  :  11  ....  tic-­‐tac  :  14  saucePan:  Le  mirepoix  est  prêt  pour  la  tomate  saucePan:  Lancement  de  la  cuisson  de  la  tomate  tic-­‐tac  :  15  ...  tic-­‐tac  :  18  pastaPan:  Les  spaghettis  sont  prêts  saucePan:  La  sauce  est  prête  Régalez-­‐vous

Page 23: La programmation asynchrone... et les pates

SCRIPT SYNCHRONE

29 MINUTES

Page 24: La programmation asynchrone... et les pates

SCRIPT ASYNCHRONE

18 MINUTES

Page 25: La programmation asynchrone... et les pates

7/10 NOTE DES INVITÉS

Page 26: La programmation asynchrone... et les pates

class  EventLoop  {      protected  $tick  =  0;      protected  $callbacksForTick  =  array();  !    public  function  executeLater($delay,  $callback)  {          $this-­‐>callbacksForTick[$this-­‐>tick  +  $delay]  []=  $callback;      }          public  function  start()  {          while  ($this-­‐>callbacksForTick)  {              $this-­‐>tick++;              $this-­‐>executeCallbacks();          }      }            public  function  executeCallbacks()  {          echo  "tic-­‐tac  :  "  .  $this-­‐>tick  .  "\n";          if  (!isset($this-­‐>callbacksForTick[$this-­‐>tick]))  {              return;  //  no  callback  to  execute          }          foreach  ($this-­‐>callbacksForTick[$this-­‐>tick]  as  $callback)  {              call_user_func($callback);          }          //  clean  up          unset($this-­‐>callbacksForTick[$this-­‐>tick]);      }  }

Page 27: La programmation asynchrone... et les pates

//  ...  $eventLoop-­‐>start();  !

//  Never  executed  $plate-­‐>serve('Régalez-­‐vous');

Page 28: La programmation asynchrone... et les pates

RESYNCHRONISER L’ASYNCHRONE

Page 29: La programmation asynchrone... et les pates

class  PlateOfSpaghettiWithSauce  extends  Plate  {      protected  $hasSpaghetti  =  false;      protected  $hasSauce  =  false;            public  function  addContentsOf(Pan  $pan)      {          parent::addContentsOf($pan);          if  ($pan-­‐>contains('Spaghetti'))  {              $this-­‐>hasSpaghetti  =  true;          }          if  ($pan-­‐>contains('Tomato'))  {              $this-­‐>hasSauce  =  true;          }          if  ($this-­‐>hasSpaghetti  &&  $this-­‐>hasSauce)  {              $this-­‐>serve('Régalez-­‐vous');          }      }  }

Page 30: La programmation asynchrone... et les pates

../..  //  sauce  $eventLoop-­‐>executeLater($delay  =  7,  function()  use  ($plate,  $eventLoop)  {      $saucePan  =  new  AsynchronousPan($eventLoop);      $saucePan-­‐>fill(new  OliveOil());      echo  "saucePan:  L'huile  chauffe\n";      $saucePan-­‐>warm($duration  =  2,  function()  use($saucePan,  $plate)  {          echo  "saucePan:  L'huile  est  chaude\n";          $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));          echo  "saucePan:  Lancement  de  la  cuisson  du  mirepoix\n";          $saucePan-­‐>warm($duration  =  5,  function()  use($saucePan,  $plate)  {              echo  "saucePan:  Le  mirepoix  est  prêt  pour  la  tomate\n";              $saucePan-­‐>fill(TomatoFactory::create());              echo  "saucePan:  Lancement  de  la  cuisson  de  la  tomate\n";              $saucePan-­‐>warm($duration  =  4,  function()  use($saucePan,  $plate)  {                  echo  "saucePan:  La  sauce  est  prête\n";                  $plate-­‐>addContentsOf($saucePan);              });          });      });  });  !$eventLoop-­‐>start();  $plate-­‐>serve('Régalez-­‐vous');

Page 31: La programmation asynchrone... et les pates

DÉMÊLER LE CODE

SPAGHETTI

Page 32: La programmation asynchrone... et les pates

$saucePan  =  new  AsynchronousPan($eventLoop);  $eventLoop-­‐>executeLater($delay  =  7,  function()  {      call_user_func($warmSaucePan);  });  $warmSaucePan  =  function()  use  ($saucePan)  {      $saucePan-­‐>fill(new  OliveOil());      echo  "saucePan:  L'huile  chauffe\n";      $saucePan-­‐>warm($duration  =  2,  $cookMirepoix);  };  $cookMirepoix  =  function()  use  ($saucePan)  {      echo  "saucePan:  L'huile  est  chaude\n";      $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));      echo  "saucePan:  Lancement  de  la  cuisson  du  mirepoix\n";      $saucePan-­‐>warm($duration  =  5,  $cookTomato);  };  $cookTomato  =  function()  use  ($saucePan)  {      echo  "saucePan:  Le  mirepoix  est  prêt  pour  la  tomate\n";      $saucePan-­‐>fill(TomatoFactory::create());      echo  "saucePan:  Lancement  de  la  cuisson  de  la  tomate\n";      $saucePan-­‐>warm($duration  =  4,  $serveSauce);  };  $serveSauce  =  function()  use  ($saucePan,  $plate)  {      echo  "saucePan:  La  sauce  est  prête\n";      $plate-­‐>addContentsOf($saucePan);  };

Page 33: La programmation asynchrone... et les pates

$saucePan  =  new  AsynchronousPan($eventLoop);  $serveSauce  =  function()  use  ($saucePan,  $plate)  {      echo  "saucePan:  La  sauce  est  prête\n";      $plate-­‐>addContentsOf($saucePan);  };  $cookTomato  =  function()  use  ($saucePan,  $serveSauce)  {      echo  "saucePan:  Le  mirepoix  est  prêt  pour  la  tomate\n";      $saucePan-­‐>fill(TomatoFactory::create());      echo  "saucePan:  Lancement  de  la  cuisson  de  la  tomate\n";      $saucePan-­‐>warm($duration  =  4,  $serveSauce);  };  $cookMirepoix  =  function()  use  ($saucePan,  $cookTomato)  {      echo  "saucePan:  L'huile  est  chaude\n";      $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));      echo  "saucePan:  Lancement  de  la  cuisson  du  mirepoix\n";      $saucePan-­‐>warm($duration  =  5,  $cookTomato);  };  $warmSaucePan  =  function()  use  ($saucePan,  $cookMirepoix)  {      $saucePan-­‐>fill(new  OliveOil());      echo  "saucePan:  L'huile  chauffe\n";      $saucePan-­‐>warm($duration  =  2,  $cookMirepoix);  };  $eventLoop-­‐>executeLater($delay  =  7,  function()  use  ($warmSaucePan)  {          call_user_func($warmSaucePan);  });

Page 34: La programmation asynchrone... et les pates

$saucePan  =  new  AsynchronousPan($eventLoop);  $warmSaucePan  =  function($callback)  use  ($saucePan)  {      $saucePan-­‐>fill(new  OliveOil());      echo  "saucePan:  L'huile  chauffe\n";      $saucePan-­‐>warm($duration  =  2,  $callback);  };  $cookMirepoix  =  function($callback)  use  ($saucePan)  {      echo  "saucePan:  L'huile  est  chaude\n";      $saucePan-­‐>fill(MirepoixFactory::create($withGarlic  =  true));      echo  "saucePan:  Lancement  de  la  cuisson  du  mirepoix\n";      $saucePan-­‐>warm($duration  =  5,  $callback);  };  $cookTomato  =  function($callback)  use  ($saucePan)  {      echo  "saucePan:  Le  mirepoix  est  prêt  pour  la  tomate\n";      $saucePan-­‐>fill(TomatoFactory::create());      echo  "saucePan:  Lancement  de  la  cuisson  de  la  tomate\n";      $saucePan-­‐>warm($duration  =  4,  $callback);  };  $serveSauce  =  function()  use  ($saucePan,  $plate)  {      echo  "saucePan:  La  sauce  est  prête\n";      $plate-­‐>addContentsOf($saucePan);  };  $eventLoop-­‐>executeLater($delay  =  7,  function()  use  ($plate,  $eventLoop)  {      Async::waterfall(          array($warmSaucePan,  $cookMirepoix,  $cookTomato),          $serveSauce      );  });

Page 35: La programmation asynchrone... et les pates

class  Async  {      public  static  function  waterfall($tasks,  $callback  =  null)      {              $taskCallback  =  function  ()  use  (&$next)  {                      call_user_func_array($next,  func_get_args());              };              $done  =  function  ()  use  ($callback)  {                      if  ($callback)  {                              call_user_func_array($callback,  func_get_args());                      }              };              $next  =  function  ()  use  (&$tasks,  $taskCallback,  $done)  {                      if  (0  ===  count($tasks))  {                              call_user_func_array($done,  func_get_args());                              return;                      }  !                    $task  =  array_shift($tasks);                      $args  =  array_merge(func_get_args(),  array($taskCallback));                      call_user_func_array($task,  $args);              };              $next();      }  }

Source: https://github.com/reactphp/async/blob/master/src/React/Async/Util.php#L81

Page 36: La programmation asynchrone... et les pates

EN ASYNCHRONE PAS DE RETURN

Page 37: La programmation asynchrone... et les pates

//  prototype  synchronous  function  $cook  =  function($ingredient)  use  ($saucePan)  {      $saucePan-­‐>fill($ingredient);      $saucePan-­‐>warm(5);      return  'chaud  devant';  };  !

!

$message  =  $cook(MirepoixFactory::create());  echo  $message,  "\n";  

Page 38: La programmation asynchrone... et les pates

//  prototype  asynchronous  function  $cook  =  function($ingredient,  $callback)  use  ($saucePan)  {      $saucePan-­‐>fill($ingredient);      $saucePan-­‐>warm(5,  function()  {          $callback('chaud  devant');      });  };  !

$cook(MirepoixFactory::create(),  function($message)  {      echo  $message,  "\n";  });

Page 39: La programmation asynchrone... et les pates

EN ASYNCHRONE PAS DE TRY/CATCH

Page 40: La programmation asynchrone... et les pates

$cook  =  function($ingredient,  $callback)  use  ($saucePan)  {      $saucePan-­‐>fill($ingredient);      $saucePan-­‐>warm(5,  function()  {          $isSummer  =  in_array(date('m'),    array(6,  7,  8)):          if  ($saucePan-­‐>contains('Tomato')  &&  !$isSummer)  {              throw  new  OutOfBoundsException('On  ne  fait                    de  la  bonne  sauce  tomate  qu\'en  été');          }          $callback('chaud  devant  !');      });  };  !

try  {      $cook(MirepoixFactory::create(),  function($message)  {          echo  $message,  "\n";      });    }  catch  (OutOfBoundsException  $e)  {      echo  "Echec  de  la  recette\n";  }

Page 41: La programmation asynchrone... et les pates

$cook  =  function($ingredient,  $callback)  use  ($saucePan)  {      $saucePan-­‐>fill($ingredient);      $saucePan-­‐>warm(5,  function()  {          $isSummer  =  in_array(date('m'),    array(6,  7,  8)):          if  ($saucePan-­‐>contains('Tomato')  &&  !$isSummer)  {              return  callback(new  OutOfBoundsException('On  ne  fait                    de  la  bonne  sauce  tomate  qu\'en  ete'));          }          $callback(null,  'chaud  devant  !');      });  };  !

$cook(MirepoixFactory::create(),  function($error,  $message)  {      if  ($error  instanceOf  OutOfBoundsException)  {          echo  "Echec  de  la  recette\n";          return;      }      echo  $message,  "\n";  });

Page 42: La programmation asynchrone... et les pates

DU CODE RÉUTILISABLE

ROBUSTE UN PLAT

CHAUD

Page 43: La programmation asynchrone... et les pates

VICTOIRE !

Page 44: La programmation asynchrone... et les pates

10/10 NOTE DES INVITÉS

Page 45: La programmation asynchrone... et les pates

IL N’Y A TOUJOURS

QU’UN SEUL CHEF

Page 46: La programmation asynchrone... et les pates

PROGRAMMATION NON

PARALLELE

Page 47: La programmation asynchrone... et les pates

PAS DE TEMPS PERDU A ATTENDRE LA RÉPONSE D’UN AUTRE

Page 48: La programmation asynchrone... et les pates

Operation                          CPU  cycles  L1  ..................  3  L2  ..................  14  RAM  .................  250  Disk  ................  41,000,000  Network  .............  240,000,000

LATENCE I/O

Page 49: La programmation asynchrone... et les pates

L1  cache  reference  .........................  0.5  ns  L2  cache  reference  ...........................  7  ns  Main  memory  reference  ......................  100  ns                            Compress  1K  bytes  with  Zippy  .............  3,000  ns    =      3  µs  Send  2K  bytes  over  1  Gbps  network  .......  20,000  ns    =    20  µs  SSD  random  read  ........................  150,000  ns    =  150  µs  Read  1  MB  sequentially  from  memory  .....  250,000  ns    =  250  µs  Round  trip  within  same  datacenter  ......  500,000  ns    =  0.5  ms  Read  1  MB  sequentially  from  SSD*  .....  1,000,000  ns    =      1  ms  Disk  seek  ...........................  10,000,000  ns    =    10  ms  Read  1  MB  sequentially  from  disk  ....  20,000,000  ns    =    20  ms  Send  packet  CA-­‐>Netherlands-­‐>CA  ....  150,000,000  ns    =  150  ms

Source: http://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf

Page 50: La programmation asynchrone... et les pates

I/O = ATTENTE ETABLISSEMENT CONNEXION SÉCURISÉE

RÉCEPTION REQUÊTE HTTP REQUÊTE BASE DE DONNÉES

LECTURE VALEUR DANS MEMCACHE LECTURE DE FICHIER SUR DISQUE

APPEL À UNE API REST ENVOI MESSAGE À UN AMQP

ENVOI RÉPONSE HTTP

Page 51: La programmation asynchrone... et les pates

90% DU TEMPS DE RÉPONSE

D’UNE REQUÊTE HTTP EST PASSÉ À ATTENDRE UNE I/O

Page 52: La programmation asynchrone... et les pates

GET  /favicon.ico

Routing Lancement de l’ordre de chargement du fichier

Déplacement de la tête de lecture Transfert des données du disque en mémoire

Envoi de la réponse HTTPTraitement

Attente Fin de la requête

Construction de la réponse HTTP

Process serveur

Page 53: La programmation asynchrone... et les pates

UN SERVEUR WEB PASSE SON TEMPS A SE TOURNER

LES POUCES

Page 54: La programmation asynchrone... et les pates

POUR MIEUX UTILISER LE CPU

ON MULTIPLIE LES PROCESS LES THREADS

ET DONC LA CONSO MÉMOIRE

Page 55: La programmation asynchrone... et les pates

MaxClients  50

Page 56: La programmation asynchrone... et les pates

UN AUTRE MONDE

EST POSSIBLE

Page 57: La programmation asynchrone... et les pates

GET  /favicon.ico

Traitement

Attente

Process serveur

I/O disque asynchrone

Transfert des données du disque en mémoire

Envoi de la réponse HTTP

I/O réseau asynchrone

Page 58: La programmation asynchrone... et les pates

LIBEL EVENT LOOP

LIBEIO ASYNCHRONOUS I/O

LIBUV MULTI-PLATFORM ABSTRACTION LAYER

Page 59: La programmation asynchrone... et les pates

GET  /favicon.icoGET  /js/jquery.jsGET  /css/main.css

Page 60: La programmation asynchrone... et les pates

COMMENT FAIRE DES I/O ASYNCHRONES

EN PHP ?

Page 61: La programmation asynchrone... et les pates

Event-­‐driven,  non-­‐blocking  I/O  with  PHP.  

Page 62: La programmation asynchrone... et les pates

PHP & PROCESS PERSISTENTS

PAS BON MÉNAGE

Page 63: La programmation asynchrone... et les pates

PHP N’A PAS DE FONCTIONS D’I/O DISQUE ASYNCHRONES

PECL/LIBIO

Page 64: La programmation asynchrone... et les pates

TANT QU’À INSTALLER UN BINAIRE

AUTANT EN PRENDRE UN

STABLE POPULAIRE

Page 65: La programmation asynchrone... et les pates

TANT QU’À REPOSER SUR UNE EVENT LOOP

AUTANT UTILISER UN LANGAGE

ÉVÈNEMENTIEL

Page 66: La programmation asynchrone... et les pates

TANT QU’À ABUSER DES FONCTIONS ANONYMES

AUTANT UTILISER UN LANGAGE

FONCTIONNEL

Page 67: La programmation asynchrone... et les pates
Page 68: La programmation asynchrone... et les pates

var  fs  =  require('fs');  fs.unlink('/tmp/hello',  function  (err)  {      if  (err)  throw  err;      console.log('successfully  deleted  /tmp/hello');  });  //  more  code  console.log('deletion  script');

Page 69: La programmation asynchrone... et les pates

plate  =  new  Plate();  pastaPan  =  new  AsynchronousPan(eventLoop);  water  =  new  Water();  pastaPan.fill(water);  console.log('pastaPan:  Starting  to  boil  water');  pastaPan.warm(duration  =  10,  function()  {      console.log('pastaPan:  Water  is  boiling');      pastaPan.fill(new  Spaghetti());      console.log('pastaPan:  Starting  to  boil  spaghetti');      pastaPan.warm(duration  =  8,  function()  {          console.log('pastaPan:  Spaghetti  is  ready');          pastaPan.remove(water);          plate.addContentsOf(pastaPan);      });  });

Page 70: La programmation asynchrone... et les pates

$plate  =  new  Plate();  $pastaPan  =  new  AsynchronousPan($eventLoop);  $water  =  new  Water();  $pastaPan-­‐>fill($water);  echo  "pastaPan:  Starting  to  boil  water\n";  $pastaPan-­‐>warm($duration  =  10,  function()  use  ($pastaPan,  $plate,  $water)  {      echo  "pastaPan:  Water  is  boiling\n";      $pastaPan-­‐>fill(new  Spaghetti());      echo  "pastaPan:  Starting  to  boil  spaghetti\n";      $pastaPan-­‐>warm($duration  =  8,  function()  use  ($pastaPan,  $plate,  $water)  {          echo  "pastaPan:  Spaghetti  is  ready\n";          $pastaPan-­‐>remove($water);          $plate-­‐>addContentsOf($pastaPan);      });  });

Page 71: La programmation asynchrone... et les pates

I/O ASYNCHRONES UN SEUL CHEF

DES CALLBACKS PLUS DE CONCURRENCE

MOINS DE CONSOL MÉMOIRE PAS POSSIBLE EN PHP, NATIF EN NODE.JS

PAS DE RETURN, PAS DE TRY/CATCH

Page 72: La programmation asynchrone... et les pates

DES PÂTES CHAUDES

Page 73: La programmation asynchrone... et les pates

MERCI

François Zaninotto - @francoisz - marmelab.com github.com/fzaninotto - github.com/marmelab