Quelles sont les implications sur la performance pour des millions de files dans un système de files moderne?

Disons que nous utilisons ext4 (avec dir_index activé) pour héberger environ 3M files (avec une taille moyenne de 750KB) et nous devons décider quel schéma de dossier nous allons utiliser.

Dans la première solution , nous appliquons une fonction hash au file et utilisons un dossier de deux niveaux (soit 1 caractère pour le premier niveau et 2 caractères au deuxième niveau): en conséquence, le filex.for hash est égal à abcde1234 , nous l'saveons on / path / a / bc /abcde1234-filex.for.

Dans la deuxième solution , nous appliquons une fonction de hachage au file et utilisons un dossier de deux niveaux (soit 2 caractères pour le premier niveau et 2 caractères au deuxième niveau): donc le filex.for hash est égal à abcde1234 , nous l'saveons on / path / ab / de /abcde1234-filex.for.

Pour la première solution, nous disposons du schéma /path/[16 folders]/[256 folders] avec une moyenne de 732 files par dossier (le dernier dossier, où le file réside).

Alors que sur la deuxième solution, nous aurons /path/[256 folders]/[256 folders] avec une moyenne de 45 files par dossier .

Étant donné que nous allons écrire / débloquer / lire des files ( mais principalement lus ) à partir de ce système beaucoup (fondamentalement le système de caching nginx), est-ce que cela dépend, dans le sens de la performance, si nous choisissons une ou une autre solution?

En outre, 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 d'annuaire est que les filesystems doivent localiser un file dans un directory, et plus le directory est grand, plus lente est cette opération.

Combien plus lent dépend de la design du système de files.

Le système de files ext4 utilise un tree B pour stocker les inputs du directory. Une search sur cette table devrait prendre le time O (log n) , la plupart du time étant inférieure à la table linéaire naïve que ext3 et aux filesystems précédents utilisés (et quand ce n'est pas le cas, le directory est trop petit pour que vraiment important).

Le système de files XFS utilise plutôt un tree B + . L'avantage de cela sur une table de hash ou B-tree est que n'importe quel nœud peut avoir plusieurs enfants b , où dans XFS b varie et peut être aussi élevé que 254 (ou 19 pour le noeud racine, et ces nombres peuvent être périmés ). Cela vous donne une complexité de time de O (log b n) , une grande amélioration.

L'un de ces filesystems peut gérer des dizaines de milliers de files dans un seul directory, XFS étant significativement plus rapide que ext4 sur un directory avec le même nombre d'inodes. Mais vous ne voulez probablement pas un seul directory avec des inodes 3M, car même avec un tree B +, la search peut prendre un certain time. C'est ce qui a conduit à créer des directorys de cette manière en premier lieu.

En ce qui concerne vos structures proposées, la première option que vous avez donnée est exactement ce qui ressort des exemples nginx. Il fonctionnera bien sur l'un ou l'autre système de files, bien que XFS ait encore un avantage. La deuxième option peut être légèrement meilleure ou légèrement pire, mais elle sera probablement très proche, même sur des repères.

Selon mon expérience, l'un des facteurs de mise à l'échelle est la taille des inodes, une stratégie de partition de hash-name.

Vos deux options proposées créent jusqu'à trois inputs inode pour chaque file créé. En outre, 732 files créeront un inode qui est encore inférieur au 16KB habituel. Pour moi, cela signifie que l'une ou l'autre option sera la même.

Je vous applaudis sur votre court hachage; les systèmes précédents sur lesquels j'ai travaillé ont pris le sha1sum du file donné et des directorys épissés basés sur cette string, un problème beaucoup plus difficile.

Certes, l'une ou l'autre option aidera à réduire le nombre de files dans un directory à quelque chose qui semble raisonnable, pour xfs ou ext4 ou quel que soit le système de files. Il n'est pas évident ce qui est mieux, il faudrait essayer de le dire.

L'indice de reference avec votre application simulant quelque chose comme la charge de travail réelle est idéal. Sinon, venez avec quelque chose qui simule de nombreux petits files spécifiquement. En parlant de cela, voici une source ouverte appelée petit file . Sa documentation fait reference à d'autres outils.

hdparm faisant des E / S soutenues n'est pas aussi utile. Il ne montrera pas les nombreuses petites E / S ou les inputs de directorys géants associées à de nombreux files.

L'un des problèmes est la façon de numériser le dossier.

Imaginez la méthode Java qui exécute l'parsing sur le dossier.

Il faudra allouer une grande quantité de memory et la désaffecter dans un court laps de time, ce qui est très important pour la JVM.

La meilleure façon est d'organiser la structure du dossier de manière à ce que chaque file se trouve dans un dossier dédié, par exemple, année / mois / jour.

La façon dont l'parsing complète est effectuée est que pour chaque dossier, il y a une exécution de la fonction afin que JVM quitte la fonction, désactive la RAM et l'exécute à nouveau sur un autre dossier.

C'est juste un exemple, mais de toute façon avoir un tel dossier énorme n'a aucun sens.