J'ai écrit un petit chenille pour numériser et recourir à des structures de répertoire.
basé sur le Dirent (qui est une petite enveloppe autour de FindnextFilea) Dans mes premiers points de repère, il est étonnamment lent: p>
environ 123473ms pour 4500 fichiers (ThinkPad T60P local Samsung 320 GB 2.5 "HD). 121481 Fichiers trouvés dans 123473 millisecondes Cette vitesse est-elle normale? P>
Ceci est mon code: P>
int testPrintDir(std::string strDir, std::string strPattern="*", bool recurse=true){ struct dirent *ent; DIR *dir; dir = opendir (strDir.c_str()); int retVal = 0; if (dir != NULL) { while ((ent = readdir (dir)) != NULL) { if (strcmp(ent->d_name, ".") !=0 && strcmp(ent->d_name, "..") !=0){ std::string strFullName = strDir +"\\"+std::string(ent->d_name); std::string strType = "N/A"; bool isDir = (ent->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) !=0; strType = (isDir)?"DIR":"FILE"; if ((!isDir)){ //printf ("%s <%s>\n", strFullName.c_str(),strType.c_str());//ent->d_name); retVal++; } if (isDir && recurse){ retVal += testPrintDir(strFullName, strPattern, recurse); } } } closedir (dir); return retVal; } else { /* could not open directory */ perror ("DIR NOT FOUND!"); return -1; } }
4 Réponses :
La toute première fois que vous effectuez un annexier récursif, vous devez probablement énumérer l'intégralité du répertoire actuel et la file d'attente de tous les annuaires que vous trouvez à visiter lorsque vous avez terminé. De cette façon, vous risquez de tirer parti de toute optimisation immédiate des optimisations de lecture en ligne NTFS pourrait faire. P>
sur les rampes de répertoires récursifs ultérieurs, si les métadonnées pour les répertoires correspondent à la cache du système, peu importe la façon dont vous le faites. P>
Edit: Clarifiez comment vous devriez visiter des annuaires. Ce n'est pas techniquement une première recherche de la largeur. P>
Cela ne va pas faire beaucoup de différence dans la pratique. Les API FindexFile à ébullition à l'API ZWQueryDirectoryFile / NTQuyDirectoryFile ( MSDN .microsoft.com / fr-US / Bibliothèque / FF567047 (vs.85) .aspx ), qui récupère l'ensemble du répertoire à la fois. Les API Findexfile utilisent déjà un tampon interne autour de cette fonction. Le but de la FindClose API est la destruction dudit tampon.
@Billy, dans ce cas, la deuxième partie de ma réponse commence :) Bien que avec un répertoire suffisamment rempli, ce tampon nécessite-t-il à nouveau sur le disque? Auquel cas la première partie s'applique aussi :)
Vous maintenez des poignées DIR ouvertes pendant la plongée récursive. Gardez plutôt une liste locale de répertoires que vous avez rencontrés et les traiter à l'extérieur de cette boucle, après la fermétrir () code>. P>
Cela va augmenter la consommation de mémoire mais il aura peu à voir avec le temps de numérisation de fichiers, qui est limité par le disque dur.
Il y a certaines circonstances où une telle vitesse est normale oui. Premièrement, l'utilisation de FindFirstFilea au lieu de FindFirstFileW va engager des frais généraux pour la conversion de l'UTF-16 vers ANSI. Deuxièmement, si vous traversez des répertoires qui n'ont pas encore été consultés par le système d'exploitation, vous encourrez au moins une pénalité de recherche (environ 16 ms pour la plupart des disques durs du consommateur), limitant votre énumération à bien moins de 100 chèques de répertoire par seconde. Cela va empirer si la table de fichiers principaux sur l'entraînement donné est mal fragmentée. P>
En ce qui concerne le nombre de fichiers, cela dépend plus du nombre de fichiers par répertoire que le nombre de fichiers eux-mêmes. P>
Un disque dur de 7200 tr / min spins 120 fois par seconde. Une rotation complète est donc un peu plus de 8 ms. Étant donné que la tête doit également bouger, le temps de recherche est distribué entre dire (2, 10ms), avec une moyenne d'environ 6 ms, plus une partie d'une rotation est nécessaire pour lire les données. Cela convient avec des heures de lecture de 8-9ms citées sur des lecteurs modernes et traditionnels. Commande de support SCSI et SATA, en tenant compte de plusieurs demandes en vol Le lecteur peut les trier et la moyenne peut peut-être 20 chiffres de bloc par rotation au lieu de 2. Autre que de surestimer le coût de recherche légèrement, votre explication est sur place.
@Ben VOIGT: Ma valeur d'~ 16 ms provient de Tom's Hardware Hard Drive Tableaux: Tomshardware.com/charts/2009-3.5-desktop-hard-drive-charts/... . Théoriquement, les lecteurs devraient fonctionner mieux que cela, mais dans la pratique, ils ne le font pas. Mes pensées étaient basées sur des graphiques il y a quelques années, lorsque 16 ms était la norme cependant. Les lecteurs modernes sont quelque part entre mes 16 et vos 8-9 chiffres.
@Ben Voigt: Notez que les disques durs pour ordinateur portable, comme celui que l'OP est testé, sont considérablement pires: Tomshardware.com/charts/2009-2.5-mobile-hard-drive-charts/...
Oui, l'OP n'a pas donné de vitesse de rotation d'entraînement, mais vous avez raison que 7200 tr / min est une mauvaise hypothèse d'un ordinateur portable. 4500 ou 5400 est beaucoup plus commun. OTOH, tant que le contrôleur est en mode AHCI, la mise en file d'attente doit être bonne pour une amélioration de l'ordre de magnitude si les demandes sont délivrées.
Probablement le lecteur est le goulot d'étranglement. Mais vous pouvez essayer: p>
alloca code>). LI>
- Les fichiersysytem utilisent unicode pour stocker des noms de fichiers? Si tel est le cas, en utilisant des chaînes UNICODE avec
FindFirstFilew code> et FindNextFileW code> peut être un peu plus rapide. Li>
ol>
Si vous avez envie de pouvoir exécuter mon outil SIZERORTER [ Color-of-Code.de/... Il ne fait pas beaucoup plus que de ramper l'arborescence de répertoires et de vérifier la taille et les horodatages et les signaler. Si la vitesse est beaucoup plus rapide, elle réside probablement à une journalisation car j'utilise du code très similaire à la vôtre.
Dupliqué possible de Comment puis-je éumérer rapidement des répertoires sur Win32?