Tester les performances,
pourquoi et comment ?

Boris Feld
Pierre-Yves David
octobus.net

Nous

Octobus

Mercurial

  • gestionnaire de version Décentralisé,
  • écrit en Python,
  • crée en 2005,
  • utilisé par Bitbucket, Facebook, Google, Mozilla, Unity,
  • outils en ligne de commandes,
  • invocation courte.

Les performances?

Performance == Fonctionnalité

Observer la production

  • colle à la réalité,

  • faible surcoûts,

  • control total de l'exécution,

  • information tardive, 🐦 🇮🇨

  • nécessite un gros flux,

  • re-déploiement rapide.

Benchmarks spécifiques

  • contrôle de l'environnent,

  • isolation, précision,

  • reproductible,

  • retour rapide,

  • écriture manuelle.

Nos besoins

Mercurial, utilitaire open source:

  • cycle de livraison mensuel,

  • base utilisateurs très diverse,

  • base utilisateurs floue,

  • pas de déploiement centralisé.

Quoi

Quoi tester ?

  • similaire aux tests fonctionnels,

  • existence de tests ≠ application testée,

  • bonne couverture essentielle,
    • différentes actions,
    • différente données.

Intégré au processus de développement

  • optimisation dirigé par benchmark,

  • enrichir sa base avec le temps,

  • détection des régressions future.

Information differente

  • temps absolue ?

  • temps maximum ?

  • évolution du temps ?

  • volatilité du temps ?

Régression 😒

Comment

Résultats comparables

Pièges

À tous les niveaux:

  • matériel,
  • noyau / système,
  • outils.

Couche matérielle

Le cloud

Pour faire des benchmarks

Le cloud

Pas de contrôle:

  • matériel variable,
  • limitation, quota,
  • pas de configuration BIOS/Noyau,
  • voisins bruyants.

littéralement

Machine physique - dédiée

BIOS

désactiver:

  • hyper-threading CPU,
  • overclocking CPU,
  • overclocking mémoire.

Couche noyau

CPU pinning

Fréquence CPU

Système de fichier

  • séparer système et benchmark,
  • disque dur à plateau et SSD
  • effet secondaire noatime.

Couche outils/logiciel

Exécutions multiples

Jamais identique

  • Variation d'une iteration à l'autre,

  • variation d'un processus à l'autre,

  • (variation d'une compilation à l'autre).

Quelles valeurs collecter?

  • minimum (égo++),

  • maximum,

  • médiane,

  • moyenne,

  • percentile ?

"perf", l'outil providentiel

  • enregistre tous les points,

  • fourni toutes les métriques,

  • enregistre l'environnement.

https://perf.readthedocs.io/en/latest/

"perf", l'outil providentiel

  • préparer le système

python -m perf system tune

variabilité

  • réalité: inévitable,

  • solution: analyse statistique,

  • résultat: régression statistiquement significative.

Détection statistique

Notre système

Composants

CPU Intel(R) Core(TM) i7-7700K
Carte-mère ASRock Z270M-ITX/ac
Mémoire Corsair Vengeance® LPX 32GB (2x16GB)
Chassis Fractal Design Core 500
Refroidissement Noctua NH-U12P SE2
2 * Noctua NF-A14
Alimentation Seasonic G-450 80PLUS Gold 450W

Résultat

  • Machine:
    • puissante,
    • petite,
    • relativement transportable,
    • économe,
    • silencieuse.
  • 1500 euros à l'achat.
  • 200 euros par an.

Logiciel: ASV

Airspeed velocity:

  • lancement du benchmark,
  • collecte des résultats,
  • affichage de graphes,
  • analyse statistique.

https://asv.readthedocs.io/en/latest/

Writing ASV benchmarks

class TimeTestSuite(object):

    def time_emptystatus(self, *args, **kwargs):
        return self._execute("status")

CRON VS SYSTEMD

CRON Systemd
Log manuel (>, tee) Log automatique (journalctl)
Multiple exécution parallèles possible Blocage des exécutions parallèles

Avantage SystemD

Unit file

/etc/systemd/system/asv.service.d/override.conf

[Unit]
Description=Run AirSpeed Velocity Benchmark

[Service]
Type = oneshot
WorkingDirectory = /home/octobus/bench/bighgperf/
User = octobus
Environment = "PATH=..."
ExecStart = /home/octobus/bench/bighgperf/launch.sh

Timer file

/etc/systemd/system/timers.target.wants/asv.timer

[Unit]
Description=Run asv every minute

[Timer]
OnCalendar=*-*-* *:*:00
Persistent=false
Unit=asv.service

[Install]
WantedBy=timers.target

Timer

$ sudo systemctl start asv.timer
$ sudo systemctl list-timers
NEXT                          LEFT     LAST                          PASSED    UNIT              ACTIVATES
Sat 2017-09-23 11:50:00 CEST  10s left Sat 2017-09-23 11:49:44 CEST  4s ago    asv.timer         asv.service

Log

$ sudo journalctl  -xef -u asv
Sep 18 13:18:26 cyanea launch.sh[23814]: [ 31.25%] ··· Running basic_commands.TimeTestSuite.time_version               ok
Sep 18 13:18:26 cyanea launch.sh[23814]: [ 31.25%] ····
Sep 18 13:18:26 cyanea launch.sh[23814]:                ====================== ==========
Sep 18 13:18:26 cyanea launch.sh[23814]:                         repo
Sep 18 13:18:26 cyanea launch.sh[23814]:                ---------------------- ----------
Sep 18 13:18:26 cyanea launch.sh[23814]:                      pypy-2017         20.9±0ms
Sep 18 13:18:26 cyanea launch.sh[23814]:                    mercurial-2017      20.9±0ms
Sep 18 13:18:26 cyanea launch.sh[23814]:                 mozilla-central-2017   20.9±0ms
Sep 18 13:18:26 cyanea launch.sh[23814]:                    netbeans-2017       20.9±0ms
Sep 18 13:18:26 cyanea launch.sh[23814]:                ====================== ==========

Commencer petit

  • Commandes simples:
    • read only (log, status, diff, …)
    • simple write (commit, …)
  • quelques dépôts:
    • Mercurial (workflow avancé),
    • Mozilla (grand taille),
    • Pypy (beaucoup de branches),
  • 39 minutes par run.

Nos résultats

Overview

Détails

Régressions

Régression détails

Régression détails range

Compare

$ asv compare -s 2b0a8b0f b5613bda

Benchmarks that have stayed the same:

       before           after         ratio
     [2b0a8b0f]       [b5613bda]
      80.7±0.01ms      80.7±0.02ms     1.00  basic_commands...
       221±0.06ms       221±0.06ms     1.00  basic_commands...
          1.28±0s          1.28±0s     1.00  basic_commands...
          3.89±0s          3.89±0s     1.00  basic_commands...

Comparaison II

Benchmarks that have got worse:

       before           after         ratio
     [2b0a8b0f]       [b5613bda]
+        33.1±0ms         42.3±0ms     1.28  basic_commands...
+        33.1±0ms         41.0±0ms     1.24  basic_commands...

Bisection

$ asv find 31ec469f..a72caf0a basic_commands.TimeTestSuite.time_version
· Running approximately 14 benchmarks within 22396 commits
· Testing <-----------------O----------------------------->
· Testing ------------------<--------------O-------------->
· Testing ---------------------------------<-------O------>
· Testing ---------------------------------<---O--->-------
· Testing -------------------------------------<-O->-------
· Testing ---------------------------------------<O>-------
· Testing ---------------------------------------<O--------
· Testing ---------------------------------------O>--------
· Testing ---------------------------------------O---------
· Greatest regression found: 800ec7c0

Conclusion

Conclusion

  • Performances = Important
  • Visibilité = Confiance
  • Benchmark = Temps 👤 💻
  • Pourquoi pas utiliser les tests?