2 votes

Les utilitaires de répertoire de l'interpréteur de commandes de MacOSX sont très lents avec les grands répertoires (millions de fichiers) - existe-t-il des alternatives ?

En raison d'un problème avec la synchronisation des contacts (je ne suis pas sûr de la source du problème, probablement un crash du programme lors d'une coupure de courant, qui a provoqué une incohérence dans le fichier de la base de données des contacts), le processus de synchronisation a créé près de 7M de fichiers dans le répertoire de la base de données des contacts. Images/ :

hostname:Images username$ pwd
/Users/username/Library/Application Support/AddressBook/Sources/4D81D34B-C932-4578-8A31-4E2E244B3875/Images

hostname:Images username$ ls
^C

hostname:Images username$ ls | wc -l
 6797073
(the result was after hours)

hostname:Images username$ cd ..
hostname:4D81D34B-C932-4578-8A31-4E2E244B3875 username$ ls -l
total 600224
-rw-r--r--@     1 username  staff     409600 Aug  2 17:43 AddressBook-v22.abcddb
-rw-r--r--@     1 username  staff      32768 Aug  3 00:13 AddressBook-v22.abcddb-shm
-rw-r--r--@     1 username  staff    2727472 Aug  2 23:26 AddressBook-v22.abcddb-wal
drwx------  65535 username  staff  231100550 Aug  2 23:26 Images
-rw-r--r--@     1 username  staff      45056 Dec  7  2017 MailRecents-v4.abcdmr
-rw-r--r--@     1 username  staff      32768 Dec  7  2017 MailRecents-v4.abcdmr-shm
-rw-r--r--@     1 username  staff       4152 Dec  7  2017 MailRecents-v4.abcdmr-wal
drwx------      5 username  staff        170 Feb 26 18:51 Metadata
-rwxr-xr-x      1 username  staff          0 Dec  7  2017 OfflineDeletedItems.plist.lockfile
-rwxr-xr-x      1 username  staff          0 Dec  7  2017 Sync.lockfile
-rwxr-xr-x      1 username  staff          0 Dec  7  2017 SyncOperations.plist.lockfile

Lorsque j'ai essayé d'utiliser les outils du shell ( ls , find ), je n'ai obtenu aucun résultat dans un temps raisonnable pour un travail interactif (c'était des heures), même en désactivant le tri des fichiers comme ls -f (ce que semble aider dans le cas d'autres OS de type UNIX ) etc. Le site ls Le processus a atteint une taille d'environ 1 Go et a fonctionné pendant des HEURES avant de produire un résultat. Ma question est la suivante : est-ce que je rate une option délicate pour que cela fonctionne raisonnablement pour les grands répertoires (en sortant les résultats en cours de route, par exemple pour les traiter davantage, les filtrer, etc.) ou est-ce que ces outils ne sont tout simplement pas écrits à l'échelle ? Ou peut-être existe-t-il de meilleurs utilitaires de fichiers/répertoires pour MacOSX (je n'ai pas essayé d'application GUI sur ce répertoire, je pense qu'il vaut mieux ne pas le faire...).

J'ai écrit un programme C assez trivial qui lit les entrées du répertoire et sort les informations au fur et à mesure :

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <unistd.h>

int main ( const int argc,
           const char * const * argv )
{
    const char * const dirpath = argv[1];
    DIR *dirp = opendir ( dirpath );
    if ( dirp == NULL )
        return (-1);

    int count = 0;
    struct stat statbuf;

    for ( struct dirent *entry = readdir ( dirp ) ;
      entry != NULL ;
      entry = readdir ( dirp ), count++ )
    {
       char filepath [ PATH_MAX + 1 ];
       memset ( filepath, 0, PATH_MAX );
       strncat ( filepath, dirpath, PATH_MAX );
       strncat ( filepath, "/", PATH_MAX );
       strncat ( filepath, entry->d_name, PATH_MAX );
       stat ( filepath, &statbuf );
       printf ("%s %llu\n", entry->d_name, statbuf.st_size );
    }
    closedir ( dirp );
    printf ("%d", count );

    return 0;
}

qui fonctionne réellement (sort le résultat après avoir lu chaque entrée) et a une empreinte mémoire d'environ 300K. Il ne s'agit donc pas d'un problème de système d'exploitation (système de fichiers, pilote, bibliothèque standard ou autre), mais d'outils qui ne sont pas très évolutifs (je sais qu'ils prennent en charge davantage d'options, etc. ls devrait mieux fonctionner, c'est-à-dire ne pas allouer 1GB de mémoire, alors que find devrait faire l'action pour chaque entrée qu'il trouve (et correspond), et non pas les lire toutes d'abord, comme il le fait apparemment...).

Quelqu'un a-t-il fait l'expérience de ce problème et a-t-il une bonne solution pour gérer des répertoires aussi volumineux (quels utilitaires utiliser) sous MacOSX (ou peut-être faut-il écrire un utilitaire système personnalisé dans ce cas) ?

(Il s'agit bien sûr d'une situation exceptionnelle, qui s'est produite pour la première fois sur mon système - mais le système d'exploitation prend en charge des répertoires de cette taille, et les outils de base de l'interpréteur de commandes devraient s'en occuper dans un délai d'un an. raisonnable manière...)

EDIT : Petite correction dans le programme (le chemin de fichier manquait '/').

2voto

t-w Points 41

Il semble donc, je me réponds, que quelqu'un trouvera peut-être mes conclusions utiles.

Les outils Unix standard (MacOSX, Linux) ne sont pas bons pour gérer les répertoires dans des situations aussi extrêmes que celles décrites. Ils sont très efficaces (peut-être aussi efficaces que possible dans ce qu'ils font) dans des situations normales - mais cette conception entraîne une utilisation extensive de la mémoire (en Go) et un temps très long pour obtenir un résultat lorsqu'un répertoire contient des millions de fichiers. Par exemple, ls lire d'abord toutes les entrées du répertoire (aussi vite que possible), et les sortir d'une liste/réseau en mémoire - cela semble être la méthode la plus efficace pour une telle tâche. Cependant, pour les cas extrêmes (avec des millions de fichiers), cette approche échoue dans la pratique, par exemple, il n'est pas possible d'apprendre quoi que ce soit sur le contenu du répertoire pendant des heures (comme dans mon cas).

D'un point de vue pratique, il serait bon que ces outils disposent d'une option permettant d'activer le traitement "en continu", c'est-à-dire de traiter les entrées en quantités gérables, par exemple par paquets de 1000 entrées (si le traitement individuel est trop lent).

Pour l'instant, il semble nécessaire de créer un utilitaire système personnalisé qui fera le travail, c'est-à-dire lister / supprimer / déplacer les fichiers dans tel répertoire. Cela pourrait probablement être fait autrement qu'en C (Python, Perl) mais comme cela pourrait être plus lent, je ne le conseillerais pas (même un petit temps multiplié par des millions peut être significatif dans l'ensemble).

Il semble que les utilisateurs non techniques n'aient pas de chance ici, ils doivent demander de l'aide.

Il est intéressant de noter que le rapport entre le temps nécessaire aux opérations sur un répertoire et le nombre de fichiers qu'il contient est le suivant non linéaire (dans ce cas, il s'agit du HFS de MacOS, les autres systèmes de fichiers peuvent varier dans les deux sens). La suppression des 6,7 millions de fichiers à l'aide du programme ci-dessus (il suffit de "délier" au lieu d'imprimer) a pris quelques jours (sur un vieil iMac avec un disque dur, pas un SSD). J'ai enregistré les noms des fichiers au fur et à mesure qu'ils étaient supprimés - au début, le rythme était d'environ 100 000 fichiers par jour, tandis que la suppression des derniers 1 à 1,5 million prenait environ 3 heures.

Merci pour les commentaires.

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X