Précédent Table des matières

3  Performances des entrées/sorties

Les quelques exercices suivants visent à montrer que l’utilisation de tampons améliore très sensiblement les performances des opérations d’entrées/sorties. Deux niveaux d’utilisation de tampons peuvent être distingués :

Il va s’agir de produire différentes versions de la commande cat et d’en comparer les performances.

Il est rappelé que la commande cat produit sur la sortie standard (STDOUT_FILENO ou stdout) le contenu des fichiers dont les noms sont fournis en paramètre. Notre implantation n’accepte aucune option.

Durée d’exécution d’une commande

La commande time affiche le temps d’exécution d’une commande donnée en paramètre. Trois informations sont reportées (voir aussi l’option -p) :

Attention, il existe aussi une commande interne du shell nommée time qui reporte ces informations sous un autre format.

La commande time qui nous intéresse est souvent placée dans /usr/bin/time. Cette version comporte une option -f permettant de spécifier le format d’affiche du résultat à la manière de printf.

Programmer en shell : les scripts shell

Un script shell est une suite de commandes shell regroupées dans un fichier dont l’exécution invoquera un shell avec la suite des commandes du fichier. Copiez dans un fichier script.sh le contenu suivant:

#!/bin/bash
# Exemple de script shell qui mesure le temps d'exécution de
# "macommande" dans les cas où la variable d'environnement
# MCAT_BUFSIZ vaut 1, 16 et 256

export MCAT_BUFSIZ
MCAT_BUFSIZ=1   /usr/bin/time -f '%e %U %S' macommande
MCAT_BUFSIZ=16  /usr/bin/time -f '%e %U %S' macommande
MCAT_BUFSIZ=256 /usr/bin/time -f '%e %U %S' macommande

Il s’agit ensuite de rendre exécutable ce fichier pour pouvoir le déclencher comme un exécutable normal:

$ chmod +x script.sh
$ ./script.sh
[...]

Les shells disposent par ailleurs, comme les langages de programmation plus classiques, de structures de contrôle. En bash par exemple, vous pouvez faire une boucle:

for((i = 0; i < 10; i++)); do
    printf '%d' "$i"
  done

pour éviter des duplications de code. Consultez la page de manuel de bash pour en savoir plus.

Tracé de courbes avec gnuplot

Gnuplot est un utilitaire de tracé de courbes. Dans sa version interactive, gnuplot accepte des commandes au prompt. Ces commandes acceptent parfois des arguments. Les arguments chaîne de caractères doivent être fournis entre quotes simples ou doubles ".

La commande plot permet de tracer des courbes. Les données sont lues depuis un fichier à raison d’un couple abscisse/ordonnée par ligne comme dans cet exemple basique, fichier ex1.dat (les # introduisent des commentaires) :

# taille duree
10   540.25
12   398.25
16   653.75

que l’on donne en paramètre à la commande plot :

gnuplot> plot "ex1.dat"

Il est possible de désigner les colonnes à considérer dans un fichier en comportant plus de deux comme celui-ci (ex2.dat) :

# taille duree vitesse
10   540.25  56
12   398.25  35
16   653.75  21

on utilise alors l’option using de la commande plot :

gnuplot> set xlabel "taille en lignes"
gnuplot> set ylabel "vitesse en octets/s"
gnuplot> plot "ex2.dat" using 1:3

L’exemple suivant, plus complet, introduit d’autres commandes et options. On utilise ici le fait qu’il est possible d’invoquer gnuplot avec en paramètre un fichier comportant des commandes

$ cat run.gnu
set title "Temps et vitesse d'execution"
set logscale x
set xlabel "taille en lignes"
set logscale y
set ylabel "temps en s ou vitesse en octets/s"
set style data linespoints
plot "ex2.dat" using 1:2 title "temps", \
     "ex2.dat" using 1:3 title "vitesse"
pause -1  "Hit return to continue"
$ gnuplot run.gnu

Exercice 24
 (Influence de la taille des tampons)   Il s’agit d’écrire une version de la commande cat utilisant directement les appels systèmes read() et write(). Le tampon est alloué dynamiquement au début de l’exécution, sa taille est définie par la variable d’environnement $MCAT_BUFSIZ. Cette version sera nommée mcat-scd (mon cat, sc pour system call — appel système, d pour allocation dynamique du tampon). On invoquera successivement la commande avec en utilisant des tampons de 1 octet à 8 Mo en doublant la taille à chaque fois.
  1. Donnez une implantation de mcat-scd.
  2. Testez cette commande sur un fichier de taille conséquente en entrée, au moins quelques dizaines de Mo. On se souciera aussi du type du système de fichiers sur lequel réside ce fichier (option -T de la commande df). La sortie pourra être redirigée vers /dev/null.
  3. Menez une campagne d’évaluation des performances de la commande en croisant le temps d’exécution de la commande (voir l’encart à propos de la commande time de mesure de temps) et la taille du tampon. On automatisera cette série d’exécutions par un script shell ; se référer à l’encart pour un exemple.
  4. Visualisez les résultats par une courbe en utilisant la commande gnuplot. Il s’agit encore de se référer à l’encart pour un exemple.

Exercice 25
 (Version appel système optimale)   Implantez maintenant une version mcat-scs (suffixe s pour static, statique) qui repose sur l’utilisation d’un tampon alloué statiquement de la taille optimale déterminée à l’étape précédente.

Exercice 26
 (En utilisant la bibliothèque standard)   Implantez une version mcat-lib qui utilise les primitives fgetc() et fputc() de la bibliothèque standard d’entrées/sorties et comparez les temps d’exécution avec la version précédente.

Exercice 27
 (Écritures en mode synchronisé)   Afin de mettre en évidence l’influence des tampons systèmes, comparez la version précédente mcat-scs avec une version mcat-osync qui positionne l’attribut O_SYNC sur le descripteur de la sortie standard.

Exercice 28
 (Synchronisation finale)   Pour terminer, produisez mcat-fsync, version modifiée de mcat_scs qui vide les tampons disque suite aux écritures par un appel à fsync() et comparez les performances avec la version précédente.

Précédent Table des matières