Forum Linux.général Améliorer les performances lors de l'accès au contenu d'un répertoire.

Posté par .
2
21
déc.
2011

Bonjour,

Je réalise quelques tests sur ma Fedora 16, relatifs au parcours d'une arborescence avec beaucoup de fichiers dedans, pour les besoins de l'exemple, plus de 160.000 fichiers vides dans un repertoire racine, et le meme nombre de fichiers, avec les même noms, dans 5 répertoires enfants (size1..5).

*** avec zsh ***

[1] [bigdir] ls -l . size* | wc -l 
960022

[2] [bigdir] time touch **/1plop.jpg 
touch **/1plop.jpg  0,16s user 1,24s system 99% cpu 1,412 total

[3] [bigdir] time  ls -l . size* | wc -l 
960022
ls --color=tty -l . size*  4,64s user 4,54s system 99% cpu 9,233 total
wc -l  0,02s user 0,09s system 1% cpu 9,230 total

Bon, le problème dans mon benchmark, ni précis ni significatif, c'est que c'est trèèès long [3]. Je sais que la structure arborescente (ou pas) est pas optimisée (c'est un héritage technique). Par contre, ce qui me surprend, c'est que le temps d’exécution de `ls' ne varie pas d'un appel à l'autre, comme si aucune info n'était mise dans le cache du système de fichiers. Et les évaluations zsh puissantes, genre **/plop1.jpg sont très lentes aussi [2].

Du coup, mes chers lecteurs, connaissez vous "la bonne façon de faire" pour lister les répertoires de façon rapide? Y a t il des réglages kernel sympa à faire pour mettre des infos en cache de façon plus agressive?

Merci pour vos conseils :)

FB

  • # Exemple curieux

    Posté par . Évalué à 7.

    Dans ton exemple, le "ls -l" a la place du "ls" n'apporte rien si ce n'est d'obliger "ls" à faire un appel système par fichier pour obtenir ses attributs ce qui doit sérieusement ralentir la chose!

    • [^] # Re: Exemple curieux

      Posté par (page perso) . Évalué à 2.

      Si tu veux compter le nombre de fichier, vaut mieux utiliser ls -1 (tiret un) pour avoir un fichier par ligne.

      Matthieu Gautier|irc:starmad

      • [^] # Re: Exemple curieux

        Posté par . Évalué à 1.

        Merci. On en apprend tous les jours !

        Si j'ai bien compris tu as un fichier par ligne mais sans les attributs, ce qui accélère le listage ?

        • [^] # Re: Exemple curieux

          Posté par (page perso) . Évalué à 2.

          getdents(2) vs stat(2)

          pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

    • [^] # Re: Exemple curieux

      Posté par (page perso) . Évalué à 0. Dernière modification le 21/12/11 à 16:44.

      absolument un

      ls -1
      
      

      serait plus pertinent
      • [^] # Re: Exemple curieux

        Posté par . Évalué à 1.

        Le -l était là pour m'affranchir des considérations de formatage du la sortie et garantir, a peu près, un fichier = une ligne. Mais -1 est là pour ça, et c'est bien mieux comme ça. Merci pour la précision!

        • [^] # Re: Exemple curieux

          Posté par . Évalué à 4.

          Les -1 et -l sont inutiles.

          La commande ls regarde si la sortie est faite sur un terminal, et dans ce cas, elle fait un affichage en colonnes en fonction de la largeur du terminal.

          Dans le cas où la sortie va dans un fichier ou dans un pipe (pipe vers wc), la commande retourne un fichier par ligne.

          • [^] # Re: Exemple curieux

            Posté par . Évalué à 1. Dernière modification le 22/12/11 à 18:18.

            C'est vrai ça dis-donc... Cependant :

            stef@wallix:~$ ls |wc -l
            104
            stef@wallix:~$ ls -l |wc -l
            105

            (J'ai fait le test deux fois pour être sûr qu'un fichier avait pas été créé entre temps)

            En fait le -l ajoute une ligne total: X... (enfin chez moi)

  • # Parallel ?

    Posté par (page perso) . Évalué à 2.

    En fait en lisant ce sujet ça m'a rappelé ces vidéos : http://tinyogg.com/watch/TORaR/ et http://tinyogg.com/watch/hfxKj/
    Ça vient du projet https://www.gnu.org/software/parallel/

    Je crois me rappeler que dans la 2ème vidéo il montre une différence de vitesse en listant (ou copiant dans son cas, de mémoire) d'une manière différente. Bref : vidéo à regarder.

    • [^] # Re: Parallel ?

      Posté par (page perso) . Évalué à 2.

      Moi ça me rappelle surtout qu'après avoir modifié coreutils pour trier les inodes avant d'en faire quoi que ce soit, les performances ont été grandement améliorées pour les répertoires avec beaucoup de fichiers : http://git.savannah.gnu.org/cgit/coreutils.git/commit/?id=24412edeaf556a

      Enfin ça s'applique sans doute pas dans ce cas ci vu que le monsieur a dit qu'il utilisait Fedora 16 (qui a sans doute ce commit intégré).

      pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

  • # Profondeur

    Posté par (page perso) . Évalué à 2.

    Je réalise quelques tests sur ma Fedora 16, relatifs au parcours d'une arborescence avec beaucoup de fichiers dedans, pour les besoins de l'exemple, plus de 160.000 fichiers vides dans un repertoire racine, et le meme nombre de fichiers, avec les même noms, dans 5 répertoires enfants (size1..5).

    Par contre, ce qui me surprend, c'est que le temps d’exécution de `ls' ne varie pas d'un appel à l'autre, comme si aucune info n'était mise dans le cache du système de fichiers.

    À mon avis c'est parceque l'information est déjà dans le cache avant le premier ls, si tu viens de créer tes fichiers. Cela te paraît plausible?

    Du coup, mes chers lecteurs, connaissez vous "la bonne façon de faire" pour lister les répertoires de façon rapide? Y a t il des réglages kernel sympa à faire pour mettre des infos en cache de façon plus agressive?

    La bonne façon c'est de ne pas avoir 160_000 fichiers par dossiers, les systèmes de fichiers non spécialisés ne sont pas fait pour ça. De mémoire, je crois qu'il n'est pas conseillé d'avoir plus d'une grosse centaine de fichiers dans un dossier, si tu veux avoir un accès rapide à tes fichiers. Je te rappelle que les fichiers dans un dossier n'ont souvent pas «d'ordre» ce qui veut dire qu'accéder à un fichier dans un dossier se fait en temps proportionnel au nombre de fichiers dans le dossier.

    Par exemple ton time touch **/1plop.jpg obtient une grosse liste de fichiers que le shell passe ensuite à touch qui va rechercher chacun des fichiers, pour cela tu vas donc ouvrir 160_000 fois le même dossier et y faire

    1 + 2 + ... + 160 000 = Q(160 000) où Q(x) = x * (x - 1) /2 (en gros x^2 / 2)

    recherches de fichiers (pour faire stat ou mettre à jour les champs, etc.)

    Si tu passes à un schéma avec 1600 dossiers imbriqués sur trois hauteurs: 32 dossiers contenant 50 dossiers contenant chacun 100 fichiers, tu va faire

    160 000 ( Q(32) + Q(50) ) ouvertures de dossiers

    et

    1600 * Q(100) traitements sur ces fichiers

    et comme Q(32) + Q(50) + Q(100)/100 est beaucoup plus petit que 160 000/2 (ça fait moins de 2000, à vue de nez)

    tu remarques une grosse différence.

    Si dans ton traitement le nombre d'appel systèmes sur chaque nom de fichier est grand, tu choppes un coefficient devant Q(160 000) pour la première méthode et le 1600 * Q(100) pour la deuxième méthode, et ça se passe de plus en plus mal pour la première méthode.

    Pour corriger ce problème, il faut donc que tu optes pour une organisation de tes fichiers sur plusieurs niveaux de profondeur.

    Par exemple, tu trouves un moyen simple de transformer ton nom de fichier en chaîne hexadecimale de 5 caractères (pour tes 160000 fichiers c'est assez), disons 12345 et tu crées un lien physique sur ton fichier de départ qui est 1/23/45 et tu fais tes traitements gourmands en appels systèmes sur cette présentation de ta collection de données.

    • [^] # Commentaire supprimé

      Posté par . Évalué à 4.

      Ce commentaire a été supprimé par l'équipe de modération.

    • [^] # Re: Profondeur

      Posté par . Évalué à 1. Dernière modification le 22/12/11 à 18:02.

      je crois qu'il n'est pas conseillé d'avoir plus d'une grosse centaine de fichiers dans un dossier

      un schéma avec 1600 dossiers imbriqués sur trois hauteurs: 32 dossiers contenant 50 dossiers contenant chacun 100 fichiers

      T'es un nazi de l'arborescence toi ;)

      Blague à part, si tu as une appli qui doit travailler sur des dizaines de milliers de fichiers semblable d'un point de vue fonctionnel mettons des vCard.

      Comment tu fais ton découpage ? 32 dossiers nommés 01,02,...,32 contenant 50 dossiers nommés 01,02,...,50 ?

      C'est peut-être mieux techniquement, mais d'un point de vue logique, si tu veux une arborescence cohérente, ça me paraît pas être une bonne solution.

      Il a y bien la solution d'avoir des dossiers a,b,c,...,z qui contiennent eux-mêmes tous les dossiers dont le nom commence par respectivment a,b,...,z

      C'est pas toujours applicable.

      • [^] # Re: Profondeur

        Posté par (page perso) . Évalué à 2.

        Comment tu fais ton découpage ?

        De façon à avoir un nombre à peu près constant d'objets dans chaque dossier feuille.

        C'est peut-être mieux techniquement, mais d'un point de vue logique, si tu veux une arborescence cohérente, ça me paraît pas être une bonne solution.

        Grâce aux liens physiques, tu peux voir tes fichiers dans plusieurs arborescences différentes: donc tu peux utiliser simultanément autant d'organisations que tu veux pour tes données. (S'y retrouver, c'est le métier de l'ordinateur.)

        • [^] # Re: Profondeur

          Posté par . Évalué à 1.

          Question : est-ce que lister des liens, physiques ou symboliques, est plus rapide que de lister de vrai fichiers ?

          • [^] # Re: Profondeur

            Posté par (page perso) . Évalué à 2.

            Pour des liens physiques cela ne fait aucune différence, le lien est juste un nouveau nom pour le même contenu de fichier.

            Les liens symboliques sont des fichiers spéciaux contenant le nom du fichiers vers lequel ils pointent, donc en principe, il faut faire une ou plusieurs recherches de dossiers pour les résoudre et retrouver le véritable nom de fichier.

            Les détails dépendent du système de fichiers (ici UFS) mais je suppose que c'est plus ou moins partout la même chose.

            Sur les systèmes HFS+ il y a une troisième sorte de liens, qui sont des liens symboliques capables de suivre un fichier lorsqu'il change de nom.

  • # De la patience chez les utilisateurs de l'informatique

    Posté par . Évalué à 8. Dernière modification le 22/12/11 à 18:10.

    c'est que c'est trèèès long

    Oulala oui 9 secondes pour lister (avec attributs s'il vous plaît) 960022 fichiers.

    Quelle patience :/

    Si tu as un script qui doit lister autant de fichiers toute les 1 seconde il y a un problème de conception de l'application à mon avis...

    C'est comme un temps de chargement "à froid" de 5 secondes pour une suite bureautique que certains trouvent inacceptable, ça me sidère.

  • # Avec find ?

    Posté par (page perso) . Évalué à 0.

    J'ai fais quelques essais dans la même configuration :

    15:12 paul@gens ~/tmp/test_dir% time  ls -1R | wc -l 
    960016
    ls --classify --tabsize=0 --literal --color=auto --show-control-chars  -1R  4,53s user 1,60s system 99% cpu 6,169 total
    wc -l  0,02s user 0,00s system 0% cpu 6,164 total
    15:13 paul@gens ~/tmp/test_dir% time find|wc -l      
    960006
    find  1,22s user 0,57s system 96% cpu 1,854 total
    wc -l  0,01s user 0,02s system 1% cpu 1,854 total
    
    

    find semble plus efficace ( gain de 5 ) ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.