10
votes

Accélérer l'accès au système de fichiers?

Mon application scanne une partie d'un système de fichiers et mes utilisateurs ont déclaré que c'était très lent lors de la numérisation d'un lecteur réseau. Test de mon code, j'ai identifié le goulot d'étranglement: les méthodes fichier.File () , fichier.isdirectory () , et fichier. / code>. , qui appelent tous fs.getboolatianattributes (fichier f) . Cette méthode semble être très lente sur les lecteurs de réseau Windows. Comment puis-je améliorer les performances? Puis-je éviter d'appeler cette méthode d'une manière ou d'une autre?


0 commentaires

5 Réponses :


10
votes

Code défensif de CodeCalls Ceux ISXYZ () Méthodes, et c'est généralement une bonne pratique. Cependant, parfois, la performance est médiocre, comme vous l'avez découvert.

Une approche alternative consiste à supposer que le fichier est un fichier, il existe, il est visible, lisible, etc., et essayez simplement de le lire. Si ce ne sont pas ces choses, vous obtiendrez une exception, que vous pouvez attraper, puis faire les chèques pour savoir exactement ce qui s'est mal passé. De cette façon, vous optimisez pour l'affaire commune (c'est-à-dire que tout va bien) et effectuez uniquement les opérations lentes lorsque les choses vont mal.


4 commentaires

Hein. C'est un moyen très intéressant de regarder le problème, mais malheureusement, il n'est pas très applicable dans mon cas. Ce que je fais, c'est la construction d'un arbre reflétant la structure de fichiers de l'utilisateur, donc j'ai un peu de déterminer si un fichier est un fichier ou un répertoire. Bien que je suppose que je pourrais utiliser ListFiles () pour faire cette distinction ... merci, vous m'avez donné quelque chose à penser!


+1 J'aime le point sur l'optimisation de la "cas commune". Vous pouvez toujours garder les chèques défensives en place pour gérer quand quelque chose n'est pas un fichier.


+1 Je viens de modifier un code de traitement de l'arborescence récursif pour utiliser ListFiles pour déterminer si le "fichier" est un répertoire; C'est une accélération mineure pour les lecteurs locaux et LAN connectés - je ne peux pas tester des disques distants VPN jusqu'à ce que je rentre chez moi. C'est aussi un code plus compact.


Si vous devez appeler ces méthodes le faire dans l'ordre qui vous permettra de courte circuiter dans la plupart des cas. Si Isfile () est vrai, il n'y a aucune raison d'appeler isdirectory () et il n'y a aucune raison d'appeler si Ishaden () est vrai.



6
votes

Comment construisez-vous cette liste de fichiers? Sauf si vous affichez chaque fichier sur le système en même temps, vous devez avoir des options ...

  1. Ne traitez que ces informations lorsque l'utilisateur le demande. par exemple. Ils cliquent sur le dossier "Windows", à quelle heure vous pourriez traiter les fichiers dans Windows.
  2. Processez ces informations dans un fil de fond, donnant l'illusion d'un meilleur temps de réponse.

    Peut-être que si vous montrez le code que vous utilisez pour créer la liste, nous pourrions trouver d'autres domaines d'amélioration. (Pourquoi ne pouvez-vous pas simplement déduire le type en fonction de la méthode utilisée pour rassembler les informations? Si vous appelez une méthode comme GetFiles (), vous savez déjà que tout est retourné est un fichier?)


4 commentaires

Vous avez raison que je puisse être paresseux et que les dossiers de chargement seulement lorsque l'utilisateur leur demande, mais il y aurait une pause chaque fois que l'utilisateur a essayé d'ouvrir un nouveau dossier, ce qui pourrait faire sentir l'arbre entier. C'est un compromis entre prendre beaucoup de temps au début et être lent tout le temps ... mais peut-être que ce ne serait pas si mauvais. Je vais devoir le tester. Merci pour les idées!


Ceci est seulement sur le réseau, correct? Les choses localement sont assez rapides? Je ne sais pas si cela importe, mais quel protocole utilisez-vous pour vous connecter?


+1 pour le traitement en arrière-plan pour améliorer les performances perçues


Oui, c'est assez rapide localement. Je ne sais pas quel protocole nous utilisons pour se connecter aux lecteurs de réseau ...



3
votes

J'ai fait face exactement au même problème

La solution de notre cas a été assez simple: puisque notre structure de répertoire suivait une norme (là où aucun répertoire qui avait le caractère "." Caractère de son nom), je viens de suivre la norme et a appliqué une heuristique très simple: "Dans notre cas, les répertoires n'ont pas le". ". caractère dans son nom ". Cette heuristique simple réduit considérablement le nombre de fois que notre application a dû appeler la fonction ISDirectory () de la classe Java.io.file.

Peut-être que c'est votre cas. Peut-être sur votre structure de répertoire que vous pouvez savoir si un fichier est un répertoire juste par ses conventions de nommage.


2 commentaires

Personnellement, je suis très réticent à écrire du code qui repose sur "Comment les choses devraient être". Pour ne pas dire que ce n'est jamais une bonne solution, mais c'est dangereux. Si quelqu'un ne connaît pas la norme ou ne le suit pas pour une raison quelconque, votre code donne des résultats incorrects. C'est une chose à donner un message d'erreur sur de mauvaises données, tout à fait une autre pour simplement échouer.


Ce serait bien si j'avais ce genre de standard à compter, mais malheureusement je ne le fais pas. : o)



2
votes

Voici un exemple de code avant et après l'utilisation de listfiles et à l'aide de isdirectory pour marcher une arborescence de répertoire (mon code utilise un rappel générique pour faire quelque chose avec chaque répertoire et fichier; si je codir c # ce serait un délégué).

Comme vous pouvez le constater que l'approche listfiles est réellement plus compacte et facilement comprise tout en étant marginalement plus rapide sur un lecteur local (950 MS vs 1000 ms) et lan-lecteur (26 secondes, vs 28 secondes), à la fois pour 23 mille fichiers.

Il est très possible que pour un lecteur connecté à distance, le speedUp pourrait être substantiel, mais Je ne peux pas tester cela du travail. Un peu surprenante, l'accélération n'est toujours qu'environ 10% sur un VPN Windows RAS à un lecteur réseau.

nouveau code xxx

code ancien xxx


0 commentaires

0
votes

Juste au cas où vous ne l'auriez pas encore essayé, appelez GetBoolantiAttributes vous-même et effectuez le masquage nécessaire sera considérablement plus rapide si vous effectuez plusieurs vérifications sur le même fichier. Bien que pas une solution parfaite (et une solution qui commence à appuyer sur votre code soit spécifique à la plate-forme), elle pourrait améliorer les performances d'un facteur de 3 ou 4. C'est une performance assez importante, même si ce n'est pas aussi rapide que possible devrait être.

La fonctionnalité JDK7 Java.nio.File.Path devrait aider ce type de chose un peu.

Enfin, si vous avez un contrôle dans l'environnement de l'utilisateur final, suggérez que vos utilisateurs configurent leur logiciel antivirus pour ne pas analyser les lecteurs de réseau. Beaucoup de Big AV Solutions (pas bien exactement ce qu'elles résolvent) ont-elles été activées par défaut. Je ne sais pas quel impact cela peut avoir sur les différentes méthodes de fichiers, mais nous avons constaté que cela a mal configuré Anit-Virus peut causer des problèmes de latence massive dans presque tous les types d'accès au fichier sur les ressources du réseau.


2 commentaires

Il serait effectivement plus rapide si je pouvais appeler gooolatianattributes () moi-même, mais malheureusement, je suis contraint à Java 1.5 et java.io.filesystem est protégé par le paquet! Barrière d'abstraction idiote, obtenue tout le temps. : o)


Vous devriez être capable d'obtenir à la méthode à l'aide de la réflexion (voir méthode.setaPestible ()) une autre astuce qui pourrait fonctionner (je ne suis pas sûr si la JVM rejettera des cours dans le Java.io pacakge si elles ne sont pas signées par Sun Sun ) Voulez-vous créer votre propre classe dans le même dossier (simplement le mettre dans un dossier Java.io dans votre pot).