Supposons que nous utilisons ext4 (avec dir_index activé) pour héberger des fichiers 3M (avec une taille moyenne de 750 Ko) et que nous devons décider du schéma de dossiers que nous allons utiliser.
Dans la première solution, nous appliquons une fonction de hachage au fichier et utilisons un dossier à deux niveaux (soit 1 caractère pour le premier niveau et 2 caractères pour le deuxième niveau): étant donc le filex.for
le hachage est égal à abcde1234, nous le stockerons sur /path/a/bc/abcde1234-filex.for.
Dans la deuxième solution, nous appliquons une fonction de hachage au fichier et utilisons un dossier à deux niveaux (soit 2 caractères pour le premier niveau et 2 caractères pour le deuxième niveau): étant donc le filex.for
le hachage est égal à abcde1234, nous le stockerons sur /path/ab/de/abcde1234-filex.for.
Pour la première solution, nous aurons le schéma suivant /path/[16 folders]/[256 folders]
avec un moyenne de 732 fichiers par dossier (le dernier dossier où le fichier résidera).
Alors que sur la deuxième solution, nous aurons /path/[256 folders]/[256 folders]
avec un moyenne de 45 fichiers par dossier.
Étant donné que nous allons écrire/dissocier/lire des fichiers (mais surtout lus) à partir de ce schéma (essentiellement le système de mise en cache nginx), cela a-t-il une importance, en termes de performances, si on choisit l'une ou l'autre solution?
De plus, quels sont les outils que nous pourrions utiliser pour vérifier/tester cette configuration?
La raison pour laquelle on créerait ce type de structure de répertoires est que les systèmes de fichiers doivent localiser un fichier dans un répertoire, et plus le répertoire est grand, plus cette opération est lente.
Le ralentissement dépend de la conception du système de fichiers.
Le système de fichiers ext4 utilise ne arborescence B pour stocker les entrées du répertoire. Une recherche sur cette table devrait prendre O (log n) temps, qui la plupart du temps est inférieur à la table linéaire naïve ext3 et précédente systèmes de fichiers utilisés (et quand ce n'est pas le cas, le répertoire est trop petit pour qu'il compte vraiment).
Le système de fichiers XFS utilise à la place un arbre B + . L'avantage de ceci sur une table de hachage ou un arbre B est que n'importe quel nœud peut avoir plusieurs enfants b , alors qu'en XFS b varie et peut atteindre 254 (ou 19 pour le nœud racine; et ces chiffres peuvent être obsolètes). Cela vous donne une complexité temporelle de O (logb n) , une amélioration considérable.
L'un ou l'autre de ces systèmes de fichiers peut gérer des dizaines de milliers de fichiers dans un seul répertoire, XFS étant nettement plus rapide que ext4 sur un répertoire avec le même nombre d'inodes. Mais vous ne voulez probablement pas un seul répertoire avec des inodes 3M, car même avec une arborescence B +, la recherche peut prendre un certain temps. C'est ce qui a conduit à créer des répertoires de cette manière en premier lieu.
Quant à vos structures proposées, la première option que vous avez donnée est exactement ce qui est montré dans les exemples nginx. Il fonctionnera bien sur l'un ou l'autre des systèmes de fichiers, bien que XFS aura toujours un petit avantage. La deuxième option peut fonctionner légèrement mieux ou légèrement pire, mais elle sera probablement assez proche, même sur les benchmarks.
D'après mon expérience, l'un des facteurs de mise à l'échelle est la taille des inodes compte tenu d'une stratégie de partitionnement par nom de hachage.
Les deux options proposées créent jusqu'à trois entrées d'inode pour chaque fichier créé. De plus, 732 fichiers créeront un inode qui est toujours inférieur aux 16 Ko habituels. Pour moi, cela signifie que l'une ou l'autre option fera de même.
Je vous applaudis pour votre court hachage; les systèmes précédents sur lesquels j'ai travaillé ont pris le sha1sum du fichier donné et les répertoires épissés basés sur cette chaîne, un problème beaucoup plus difficile.
Certes, l'une ou l'autre option aidera à réduire le nombre de fichiers dans un répertoire à quelque chose qui semble raisonnable, pour xfs ou ext4 ou tout autre système de fichiers. Ce n'est pas évident qui est mieux, aurait à tester pour le dire.
La comparaison avec votre application simulant quelque chose comme la charge de travail réelle est idéale. Sinon, imaginez quelque chose qui simule spécifiquement de nombreux petits fichiers. En parlant de ça, en voici un open source appelé smallfile . Sa documentation fait référence à d'autres outils.
hdparm
faire des E/S soutenues n'est pas aussi utile. Il n'affichera pas les nombreuses petites E/S ou entrées de répertoire géantes associées à de très nombreux fichiers.
L'un des problèmes est la façon de numériser le dossier.
Imaginez Java qui exécute l'analyse sur le dossier.
Il devra allouer une grande quantité de mémoire et la désallouer en peu de temps, ce qui est très lourd pour la JVM.
La meilleure façon est d'organiser la structure des dossiers de la façon dont chaque fichier est dans un dossier dédié, par ex. année mois jour.
La façon dont l'analyse complète est effectuée est que pour chaque dossier, il y a une exécution de la fonction, donc JVM quittera la fonction, désallouera RAM et la réexécutera sur un autre dossier.
Ce n'est qu'un exemple, mais de toute façon avoir un dossier aussi énorme n'a aucun sens.
J'ai eu le même problème. Essayer de stocker des millions de fichiers sur un serveur Ubuntu en ext4. Fin de l'exécution de mes propres repères. J'ai découvert que le répertoire plat fonctionne bien mieux tout en étant plus simple à utiliser:
A écrit un article .