Micro-performance

Astuces et Indications sur l'exécution de scripts PHP

Quoi ?

La micro-performance, c'est :

 

  • Simplifier un code pour diminuer le nombre d'opérations machine
  • Réduire la complexité d'une application
  • Optimiser l'architecture d'une application
  • Conserver et améliorer la lisibilité pour l'humain

Pourquoi ?

  • Économiser les ressources matérielles
  • Stabiliser les applications
  • Chargement plus rapide pour l'utilisateur

Comment ?

  • Regarder sous le capot
  • Se mettre à la place de la machine (cf. Freud)
  • Penser KISS
  • Voir KISS
  • Manger KISS

Y'aura du cache

C'est la réponse de beaucoup d'acteurs du web, surtout sur les grosses applications. Le cache c'est comme le parfum, ça sent bon seulement quand on dose bien.

On rajoutera des machines

La prochaine fois que vous croiserez quelqu'un du service compta, je ne pourrai plus rien pour vous.

Mais après tout...

Un exemple de code à améliorer


        $conn = $this->getEntityManager()->getConnection();
        $qb = $conn->createQueryBuilder();
        $qb->select("o.type")
            ->from("organization__organization", "o")
            ->where("o.{$column}=:organization_property");
        $qb->setParameter("organization_property", $value);
        $type = $qb->execute()->fetch();

Possibilité d'amélioration


        $type = $this
            ->getEntityManager()
            ->getConnection()
            ->createQueryBuilder()
            ->select("o.type")
            ->from("organization__organization", "o")
            ->where("o.{$column}=:organization_property")
            ->setParameter("organization_property", $value)
            ->execute()
            ->fetch()
        ;

Gérer sa RAM

Comment ça fonctionne ?

Le moteur Zend utilise une unité de mémoire, la Zval. Elle contient :

  • Un compteur de références
  • Un booléen is_ref
  • Une valeur

Les scopes

  • Les variables initialisées dans le scope global sont en mémoire jusqu'à la fin du script.

 

  • Les variables initialisées dans le scope local, à l'intérieur d'une fonction, sont supprimées dès la fin de la fonction.

 

  • Une variable initiée dans le scope local mais faisant l'objet d'une référence extérieure ne sera pas supprimée à la fin de la fonction => risque de fuite de mémoire.

Les pièges

Les références circulaires

Solution I

class ParentTest {

    protected $child;
    public function __construct(){
        $this->child = new ChildTest($this);
    }
}

class ChildTest {
    protected $parent;
    public function __construct(ParentTest $parent) {
        $this->parent = $parent;
    }
}

Résultats Solution I

Solution II

class ParentTest {

     // ...

    public function __destruct(){
        unset($this->child);
    }
}

class ChildTest {

    // ...
    public function __destruct() {
        unset($this->parent);
    }
}

Résultats Solution II

Le Garbage Collector

  • Tampon de racines (Root Buffer)
  • Collecte les références inutilisées
  • Assez lourd à l'exécution

Résultats Solution III

Temps d'Exécution

Les fonctions récursives

Exemple

function recursiveFunction($i{

    $object = new HeavyObject();
    // Opérations sur $object

    if($i % 10000 === 0) {
        echo memory_get_usage() . '<br>';
    }
    if($i < 100000) {
        $i++;
        recursiveFunction($i);
    }
}

Sortie

801600
12230496
23724864
34170656
46713600
57683208
68129000
82769096
93214888
104184496

Made with Slides.com