Previous Up

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. En dehors des commandes habituellement utilisées en interactif, un shell reconnaît aussi des commandes telles des if ou for permettant le contrôle du flux d’exécution. Vous pourrez vous inspirer de l’exemple fourni ici. Sauvegardez le contenu suivant dans un fichier mcat.sh

#! /bin/sh -uf
#
# mcat -- campagne d'appels à mcat-scd
#
# squelette de shell script

# La commande à tester
MCAT=./mcat-scd
# le fichier à lui mettre en entrée
MCAT_INPUT=bigfile
# Le fichier de temps à générer
TIME_FILE=mcat-tm.dat

# la commande gnu time
TIME_CMD="/usr/bin/time"
# les options de cette commande
TIME_OPT="-f %e %U %S"

# initialisation du fichier de résultats
rm -f $TIME_FILE && echo "# real user sys" > $TIME_FILE

# un exemple de boucle
for str in  foo bar gee ; do 
    echo $str
done

# un autre exemple de boucle
for size in `awk 'BEGIN { for( i=1; i<=8388608; i*=2 ) print i }'`; do
    export MCAT_BUFSIZ=$size
    echo $MCAT_BUFSIZ 
done

# un exemple de redirection des sorties standard et d'erreur
$TIME_CMD "$TIME_OPT" ls > /dev/null 2>> $TIME_FILE

# eof

Il s’agit ensuite de rendre exécutable ce fichier :

% chmod +x mcat.sh

que l’on peut ensuite invoquer :

% ./mcat.sh
foo
bar
gee
1
2
4
8
[...]
% cat mcat-tm.dat
# real user sys
 0.01 0.00 0.01

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 30
 (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 mact-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, typiquement 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 31
 (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 32
 (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 33
 (Écritures en mode synchronisée)   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 34
 (Synchronisation finale)   Pour terminer, produisez mcat-fsync, version modifiée de mcat_scs qui vide les tampons disques suite aux écritures par un appel à fsync() et comparez les performances avec la version précédente.

[fin provisoire du sujet...]


Previous Up