IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Performance accès fichiers IO.File


Sujet :

Java

  1. #1
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut Performance accès fichiers IO.File
    Bonjour

    J'ai une fonction qui calcule le nombre de fichiers et de répertoires avec io.File
    mais celle-ci est bcp trop longue. (Contenu : 86260 Fichiers 15702 Dossiers
    pour time :25007 ms )
    Existe-t-il une meilleure implémentation que File ? ou autre ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
        public static int nbRepertoire(String chemin){
            String list [];
            File r= new File(chemin);
            File f=null;
     
            if (r.isDirectory()){
              list = r.list();
              if (list==null) return 0;
              for (int i = 0; i < list.length; i++){
                f= new File(chemin+"\\"+list[i]);        
                if (f.isDirectory()) {
                	nbd++;
                	nbRepertoire(chemin+"\\"+list[i]);
                }
                if (f.isFile()) {
                	nbf++;
                }
              }
            }
              return 1;
          }
    Thnaks

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Par défaut
    Bonjour,

    Apache fournit une classe utilitaire qui permet (entre autre) de lister des fichiers/dossiers : FileUtils . Cette classe fait partie de la librairie Commons IO.

    Tu peux faire un test pour voir les performances...

    Romain.

  3. #3
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    Les performances sont pires encore:

    en utilisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Collection<File> files =FileUtils.listFilesAndDirs(baseDirectory, TrueFileFilter.INSTANCE, DirectoryFileFilter.DIRECTORY);
    et une boucle c'est la cata.

    Avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Collection<File> files2 =FileUtils.listFiles(baseDirectory, null, true);
    			    Collection<File> files3 =FileUtils.listFilesAndDirs(baseDirectory, new NotFileFilter(TrueFileFilter.INSTANCE), DirectoryFileFilter.DIRECTORY);
    et un .size() encore plus long.

    Scanning base directory:
    86853
    15963
    time :34758 ms

    Bref faut changer de méthode

    Qui aurait une solution ? (Je souhaite juste le nombre de fichier/repertoire sans les noms et/ou attributs )

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Par défaut
    Si on reprend ton précédent code essai ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    public static int nbRepertoire(String chemin){
            String list [];
            File r= new File(chemin);
            File f=null;
     
            if (r.isDirectory()){
              list = r.list();
              if (list==null) return 0;
              for (int i = 0; i < list.length; i++){
              String cheminFichier  = new StringBuilder(chemin).append(File.separatorChar).append(list[i]).toString();
                f= new File(cheminFichier);        
    if (f.isFile()) {
                	nbf++;
                }            
    else if (f.isDirectory()) {
                	nbd++;
                	nbRepertoire(cheminFichier);
                }
     
              }
            }
              return 1;
          }
    Mais je ne suis pas sûr que ça influe beaucoup. Vu le nombre de fichiers que tu as à lister les perfs ne me paraissent pas catastrophiques... Tout dépend aussi du disque dur que tu as.

    Romain.

  5. #5
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    merci Romain
    Mais c'est pareil...

    Emplacement:
    ------------------
    Contenu : 86679 Fichiers 15877 Dossiers
    ------------------
    time :18064 ms

    18 s pour qq dizaines de milliers de fichiers... ca me parait abyssal !
    Je ne pense pas que les perfs du disque soit en cause ici (je passerai sur les temps de déplacement du bras...)
    Il s'agit juste de lire une table (Master File Table si je ne me trompe) en NTFS . Je pense que le pb vient de la creation des objets Files ou de la structure de recherche.

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par rg77140 Voir le message
    Mais je ne suis pas sûr que ça influe beaucoup.
    Non c'est même inutile puisque la concaténation de String est remplacé automatiquement par des StringBuilder. Du coup c'est juste pas lisible.
    Pire cela peut supprimer quelques optimisations du compilateur...

    C'est lorsqu'on fait plusieurs concaténation dans des boucles (avec += par exemple) qu'il faut utiliser un StringBuilder...



    Citation Envoyé par aspire Voir le message
    Il s'agit juste de lire une table (Master File Table si je ne me trompe) en NTFS
    C'est quand même couteux car tu doit récupérer les stats de tous les fichiers... C'est ca qui doit être lourd.



    Ce que tu peux faire coté Java c'est d'utiliser listFiles() à la place de list(), ce qui te permet de récupérer directement un objet File (plus besoin de la conversion String->File).

    Après il y a une petite astuce pour les répertoires contenant plein de fichier, qui consiste à utiliser une FileFilter qui n'accepte aucun fichier, mais dans lequel tu fais tes traitements.
    Cela permet simplement d'éviter de créer de gros tableau de File[], et donc d'encombrer inutilement la mémoire.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    	static class FileCount {
    		int files = 0;
    		int directories = 0;
    	}
     
    	public static FileCount nbRepertoireList(String chemin) throws IOException {
    		final FileCount count = new FileCount();
    		FileFilter filter = new FileFilter() {
    			@Override
    			public boolean accept(File pathname) {
    				if (pathname.isDirectory()) {
    					count.directories++;
    					pathname.listFiles(this);
    				} else {
    					count.files++;
    				}
    				return false;
    			}
    		};
    		filter.accept(new File(chemin));
    		return count;
    	}
    Mais je doute que ton problème viennent de là... mais plutôt des accès IO sur les fichiers. Notamment le isDirectory() qui peut être assez couteux





    Si tu tournes sous Java 7, tu peux t'orienter vers l'API NIO.2 qui améliore grandement l'accès au système de fichier, avec notamment la méthode Files.walkFileTree() qui permet de parcourir une arborescence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    	public static FileCount nbRepertoireWalk(String chemin) throws IOException {
    		final FileCount count = new FileCount();
     
    		Files.walkFileTree(Paths.get(chemin), new SimpleFileVisitor<Path>() {
    			@Override
    			public FileVisitResult preVisitDirectory(Path dir,
    					BasicFileAttributes attrs) throws IOException {
    				/* On visite un répertoire */
    				count.directories++;
    				return FileVisitResult.CONTINUE;
    			}
     
    			@Override
    			public FileVisitResult visitFile(Path file,
    					BasicFileAttributes attrs) throws IOException {
    				/* On visite un fichier */
    				count.files++;
    				return FileVisitResult.CONTINUE;
    			}
     
    			@Override
    			public FileVisitResult visitFileFailed(Path file, IOException exc)
    					throws IOException {
    				/* Il y a eu une erreur qui fait qu'on n'a pas vu visiter le fichier/répertoire */
    				if (Files.isDirectory(file))
    					count.directories++;
    				else
    					count.files++;
    				return FileVisitResult.CONTINUE;
    			}
    		});
    		return count;
    	}


    a++

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Par défaut
    J'ai fait d'autre modifs :
    - Utilisation de constante au lieu d'instancier un nouveau string à chaque fois "\\"
    - Utiliser un else if au lieu de 2 if à la suite
    - Effectuer la concaténation de string une seule fois au lieu de deux
    - Et l'utilisation du StringBuilder qui normalement est déjà fait par la JVM tu as raison.

    ça lui a fait gagner un peu de temps (18 secondes au lieu de 25) mais je m'attendais à ce que ça ne lui fasse pas gagner un temps fous non plus...

    Romain.

  8. #8
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut timed batch file
    Merci pour toutes ces infos...
    je ne pense pas que le temps de latence vienne des opérations minimes faites sur les chaines
    @adiGuba: je confirme que isDirectory est extrêmement lent.
    Et certains répertoires retournent des listes bien pleines. Je vais essayer le FileFilter juste pour voir.

    Mais je suis d'accord tout le problème vient des accès disques. Pour fixer les idées j'ai lancé un script batch de mon appli java avec un exec qui fait le travail avec une boucle FOR IN DO et une instruction dir les résultats sont sans appel

    Beginning at: 13:11:37,35
    Running Timed Batch File

    Debut script a: 13:11:37,35

    86272
    fin nb fichier : 13:11:45,79
    15881
    fin nb repertoire : 13:11:49,66

    Timed Batch File Completed
    Start time: 13:11:37,35
    Stop time : 13:11:49,67
    Total time: 0:00:12.32

    12s pour le script soit 6s de moins que la fct java la + performante.
    Bon j'ai un petit souci sur le nombre de fichiers (il doit y avoir des fichiers sans extension...) mais le volume reste le même.
    En fait ce qui m’étonne quand même c'est l'usage "abusif" (?) des listes sur des structures arborescentes...???

  9. #9
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut time of time
    And the winner is :

    méthode recursive IO.FIle
    ------------------
    Contenu : 86352 Fichiers 15883 Dossiers
    ------------------
    time :19640 ms

    méthode FileFilter (de adiGuba)
    86352
    15884
    time :14416 ms

    en revanche pourquoi dis tu que cela évite les tableaux de File ? ListFile ds accept renvoie bien des tableaux de File ,non ???

  10. #10
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par aspire Voir le message
    en revanche pourquoi dis tu que cela évite les tableaux de File ? ListFile ds accept renvoie bien des tableaux de File ,non ???
    Oui... mais elle retourne un tableau contenant uniquement les File dont accept() retourne true, ce qui n'est jamais le cas de mon code

    Bref au lieu de créer un gros tableau et de parcourir les éléments, on parcours les éléments via le FileFilter et on crée un tableau vide (ce qui a un coût ridicule).


    a++

  11. #11
    Membre actif
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Par défaut
    Bien vu le "détournement" de accept() c'est un peu comme faire un tri sur place.
    Encore une question : la nouvelle api nio2 surement plus étoffée en fonctionnalité, vaut-elle vraiment le coup en terme de perf ?
    J'ai aussi vu un FileSystemView qui accède au données disque, y aurait-il un moyen de récupérer les infos ?
    Pour mon probleme de perf je vais mettre une limite sur le nombre de fichier, mais je suis déçu : je pensais vraiment etre sous les 10s pour 100k fichiers...

  12. #12
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par aspire Voir le message
    Encore une question : la nouvelle api nio2 surement plus étoffée en fonctionnalité, vaut-elle vraiment le coup en terme de perf ?
    Oui !
    Chez moi walkFileTree() était nettement plus rapide...


    Citation Envoyé par aspire Voir le message
    J'ai aussi vu un FileSystemView qui accède au données disque, y aurait-il un moyen de récupérer les infos ?
    FileSystemView.getFileSystemView()


    a++

Discussions similaires

  1. Accès fichiers médias protégés et performances
    Par zevince dans le forum Langage
    Réponses: 2
    Dernier message: 24/10/2012, 14h43
  2. Accès fichier File.exists() et WindowsIdentity
    Par yukafrisbee dans le forum C#
    Réponses: 8
    Dernier message: 10/04/2012, 17h00
  3. input type="file" bloque la modification chemin accès fichier
    Par link256 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 03/09/2008, 14h57
  4. [OC4J][Tomcat][Accès fichier] spécification "file:\\&qu
    Par Jaxofun dans le forum Tomcat et TomEE
    Réponses: 3
    Dernier message: 04/08/2005, 09h56
  5. [Kylix] accés fichiers
    Par sdoura dans le forum EDI
    Réponses: 4
    Dernier message: 08/10/2002, 19h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo