ls

Hier, je suis tombé sur un truc qui m’a éberlué. Je le partage, même si c’est un truc un peu avancé.

Introduction

Dans un système de type Unix, comme Linux ou macOS, la commande ls permet de lister les fichiers d’un répertoire.

La commande ls

Auparavant, les terminaux étaient en noir et blanc. Maintenant, les gens aiment bien les couleurs et la commande ls affiche les noms des fichiers en couleur, selon leur type et leur attribut.

Quelqu’un s’en plaint que l’affichage de plus de 10 000 fichiers prenaient du temps. Un administrateur système, Joshua Stein, s’est penché sur le problème et a trouvé une solution plutôt simple.

Trouver le problème

Expliquer le tout permettra de montrer un processus pour découvrir un problème et le régler sous un système de type Unix. L’équivalent peut se faire sous Windows, mais avec d’autres outils.

La première étape est de créer un environnement de test pour reproduire le problème. Si nous ne pouvons observer le problème, nous ne pourrons pas le régler.

Dans le cas qui nous occupe, c’est assez simple : il suffit de créer un répertoire contenant beaucoup de fichiers. Nous n’avons pas besoin de fichiers réels, car seul le listage nous intéresse. Nous allons donc créer des fichiers vides. Dans un terminal, tapez les commandes suivantes :

Créer un environnement de test

mkdir permet de créer un répertoire (make directory).

cd permet de changer de répertoire courant (change directory).

touch actualise un fichier. Si le fichier n’existe pas, il est créé. {1…10000} est une itération de 1 à 10000. Autrement dit, les fichiers fichier1.txt, fichier2.txt, fichier3.txt jusqu’à fichier10000.txt sont créés.

Maintenant, mesurons combien de temps il faut pour afficher ces 10 000 fichiers :

Temps nécessaire pour ls 10 000 fichiers

La commande time permet de calculer le temps d’exécution de la commande en paramètre, dans notre cas, la commande ls. Le paramètre –colors=always est utilisé pour forcer l’utilisation des couleurs. Par défaut, ls va lister le nom des 10 000 fichiers. Cela ne nous est pas utile. Nous redirigeons la sortie dans la commande wc (word count), avec le paramètre -l (pour line). Donc, au lieu d’afficher les noms des fichiers, le nombre de fichiers est affiché.

Sur mon ordinateur pas très performant, cela prend 0,154. Joshua Stein avait des résultats pires que cela. Voyons ce qui prend du temps.

strace de ls

La commande strace permet de tracer un programme. Dans le cas qui nous occupe, la commande affiche le nombre de fois que chaque fonction est appelée.

Nous avons 10 000 appels à lstat. Ce qui est étrange et mérite d’être fouillé davantage.

La commande man lstat affiche la documentation de la fonction lstat (man pour manuel).

man lstat

La fonction lstat retourne les informations sur un fichier. Elle est ainsi appelée parce que les fichiers sont colorés en fonction de leur type. Si nous désactivons la couleur en fonction du type, nous allons éliminer ces 10 000 appels à lstat.

Corriger le problème

Les couleurs employées par ls sont définies avec la variable d’environnement LS_COLORS :

echo $LS_COLORS

Il y a beaucoup de monde. Si nous désactivons le tout, nous aurons de bien meilleures performances.

Pour définir LS_COLORS :

LS_COLORS=’ex=00:su=00:sg=00:ca=00:’

Vérifions le tout.

strace de ls après la modification à LS_COLORS

Les appels à lstat ont disparu.

time ls avec les modifications à LS_COLORS

Nous sommes passés de 0,154 seconde à 0,107 secondes.

En terminant

C’est ainsi que nous optimisons un système, en regardant ce qui se passe, puis en comprenant pourquoi et enfin en modifiant l’environnement pour gagner du temps. Il est important de pouvoir mesurer les progrès. Autrement, nous ne pouvons juger de l’optimisation.

Merci à Joshua Stein d’avoir partagé sa trouvaille. Joshua Stein est entre autres un développeur OpenBSD que je suis depuis des années.

Son post original se trouve ici :

https://news.sherlock.stanford.edu/posts/when-setting-an-environment-variable-gives-you-a-40-x-speedup