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) :
- le temps écoulé entre le début et la fin de la commande (elapsed time ou real time) ;
- le temps processeur utilisé en mode utilisateur (user time) ;
- le temps processeur utilisé en mode système pour le compte du programme (system time ou kernel time).
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 # eofIl s’agit ensuite de rendre exécutable ce fichier :
% chmod +x mcat.shque 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.01Tracé 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.75que 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 21on 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:3L’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.
- Donnez une implantation de mcat-scd.
- 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.
- 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.
- 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...]
![]()
![]()