2009-10-27 5 views
1

Nous avons un problème sous Linux avec les inodes de répertoire qui deviennent plus volumineux et lents à naviguer dans le temps, car de nombreux fichiers sont créés et supprimés. Par exemple:Inodes de répertoire Unix - fragmentation et vidage du contenu du répertoire

% ls -ld foo 
drwxr-xr-x 2 webuser webuser 1562624 Oct 26 18:25 foo 
% time find foo -type f | wc -l 
    518 
real 0m1.777s 
user 0m0.000s 
sys  0m0.010s 

% cp -R foo foo.tmp 
% ls -ld foo.tmp                  
drwxr-xr-x 2 webuser webuser  45056 Oct 26 18:25 foo.tmp 
% time find foo.tmp -type f | wc -l 
    518 
real 0m0.198s 
user 0m0.000s 
sys  0m0.010s 

Le répertoire d'origine a 518 fichiers, prend 1,5 Mo pour représenter, et prend 1,7 secondes pour traverser.

Le répertoire reconstruit a le même nombre de fichiers, prend 45K à représenter et 0,2 seconde à parcourir.

Je me demande ce que cela pourrait causer. Ma supposition est la fragmentation - ce n'est pas supposé être un problème avec les systèmes de fichiers Unix en général, mais dans ce cas nous utilisons le répertoire pour les fichiers de cache à court terme et ainsi créons, renommons et supprimons constamment un grand nombre de petits fichiers . Je me demande aussi s'il existe un moyen de vider le contenu binaire littéral du répertoire - c'est-à-dire lire le répertoire comme s'il s'agissait d'un fichier - ce qui me donnerait peut-être un aperçu de la taille de ce répertoire. Ni lu() ni sysread() de Perl me permettra de:

swartz> perl -Mautodie -MPOSIX -e 'sysopen(my $fh, "foo", O_RDONLY); my $len = sysread($fh, $buf, 1024);' 
Can't sysread($fh, '', '1024'): Is a directory at -e line 1 

Informations système:

Linux 2.6.18-128.el5PAE #1 SMP Wed Dec 17 12:02:33 EST 2008 i686 i686 i386 GNU/Linux 

Merci!

Jon

+0

Peut-être que vous devriez expérimenter avec différents systèmes de fichiers. Essayez xfs. – Artelius

+0

Veuillez spécifier le système de fichiers que vous utilisez. – camh

Répondre

2

Pour la question 1, la fragmentation externe provoque normalement une surcharge d'environ 2x ou plus, 1 plus vous avez la fragmentation interne de granularité d'allocation. Aucun d'eux ne vient expliquer votre observation. Donc, je ne pense pas que ce soit une fragmentation normale à l'état stationnaire.

La spéculation la plus évidente est que 1,5 Mo est la marque de haute mer; à un moment donné, il avait vraiment 1,5 Mo d'octets d'entrées ou 1,5 Mo/2 octets d'entrées avec la fragmentation attendue.

Une autre spéculation est que la règle de 50% est vaincue par une allocation non-markovienne. Imaginez que je nomme les fichiers avec "tmp% d", donc, tmp1, tmp2, ... tmp1000, tmp1001, ...

Le problème ici est que rm tmp1 ne fait pas de place pour tmp1001. C'est évidemment une supposition sauvage.

Q2: Il n'y a pas un bon moyen de lire le répertoire brut. AFAIK, vous devez soit pirater le noyau, soit utiliser debugfs pour changer le type d'inode, le lire, puis le changer, ou utiliser debugfs pour lire l'inode, obtenir les numéros de blocs, puis lire les blocs. Une approche de débogage fonctionnelle est probablement plus raisonnable.

Vous pouvez résoudre le problème de performances en vous assurant que l'indexation est activée. Voir tune2fs.


cinquante pour cent règle de Knuth: dans l'état stable, 50% des opérations sont des allocations, 50% sont Libère, 50% des blocs libres fusion, puis les trous sont 50% des allocations, et 50% de l'espace est gaspillé. (Aka, 100% frais généraux.) Ceci est considéré comme "normal". Malloc a le même problème.

+0

Bonne réponse, merci. Nous avons eu une grande augmentation temporaire de # fichiers à un moment donné, donc votre "spéculation évidente" a un certain mérite (et malheureusement ce n'était pas évident pour moi jusqu'à ce que vous le signaliez :)) –

0

Cela se produit en raison de la fragmentation due à la création et à la suppression de fichiers réitérés. Au fur et à mesure que la taille de l'inode augmente, elle ne rétrécit plus jamais, donc elle reste grande même si elle est presque vide.

Je pense que vous avez principalement deux mesures pour faire face au problème:

  1. construire une structure de sous-répertoires afin d'éviter un trop grand nombre d'enfants de moins d'un parent seul répertoire. Par exemple, si vous créez des fichiers dont le chemin a un format tel que dir/file-%06d, vous induisez un million d'enfants avec leur inode de répertoire énorme attendu. Vous préférez concevoir une structure de sous-arbre décomposant les noms de fichiers en leurs préfixes variables, par exemple, si votre fichier est file-123456.ext, allouez-les sous quelque chose comme dir/files/1/2/3/4/123456.ext. Cette stratégie limitera le nombre maximal d'enfants à 1000 sous la feuille de répertoire finale. Le niveau de decompositon dépend de la taille de la partie variable du nom de fichier. À titre de contre-mesure, une fois que vous avez déjà d'énormes inodes de répertoire, il ne vous reste plus qu'à créer un nouveau répertoire frère (small-inode) pour déplacer tous les fichiers originaux (.) Dans le nouveau répertoire, pour supprimer le répertoire d'origine et renommer le nouveau répertoire en son nom d'origine. Méfiez-vous des services en cours d'exécution sous le chemin d'origine.

Certains shell-fu impliquant find et stat --printf='%b' ou %s sur les répertoires peut vous aider à détecter d'autres endroits gênants dans votre système de fichiers, et les mettre sous une observation plus attentive.

Pour plus de détails du système de fichiers spécifiques, look at this post in ServerFault.com

Questions connexes