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

SL & STL C++ Discussion :

Performances en lecture d'un fichier (std::getline)


Sujet :

SL & STL C++

  1. #1
    Membre émérite

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Par défaut Performances en lecture d'un fichier (std::getline)
    Bonjour,

    J'ai besoin de lire et parser un fichier d'une taille de 11 Mo contenant 180 000 lignes.
    J'ai utilisé le code suivant pour effectuer un test de temps de lecture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::ifstream geomFile(name);
    std::string myLine;
    while(std::getline(geomFile, myLine));
    Cela prend environ 5 secondes.
    Je trouve cela un peu lent et je voulais savoir si c'est normal que ce soit aussi lent ou bien si cela vient de la fonction getline(), du compilateur visual c++6 ou autre chose...
    Merci.

    PS : mon ordinateur est récent.

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    577
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 577
    Par défaut
    as-tu essayé avec d'autres fonctions ?
    fonctions C --> fgets() par exemple ... pour comparer les perf ?

    @+

  3. #3
    Invité
    Invité(e)
    Par défaut
    il y a peut etre d'autres solutions ; cela dépend de ce que tu veux faire du contenu du fichier...

    par exemple, lire le fichier en entier, brut de brut, et compter le nombre de '\n'...

  4. #4
    Membre émérite

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Par défaut
    J'ai pas trop envie de retourner au langage c et les char * mais bon s'il faut ça pour les performances ...

    Le fichier il faut que je le lise en entier, parce que c'est un fichier de géométrie 3D que je charge dans une structure de données.
    Je me pose la question de lire tout d'un coup dans un buffer mais c'est peut être un peu bourrin.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par TheSeb
    Je me pose la question de lire tout d'un coup dans un buffer mais c'est peut être un peu bourrin.
    la meilleure facon de comparer les performances, outre de comparer l'assembleur généré, c'est encore de tester...

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Salut,

    Le problème des performances en lecture d'un fichier est multiple:

    En vrac, et rien qu'au niveau du matériel, on peut estimer que cela peut dépendre de la position du fichier par rapport aux tetes de lecture du disque (si le fichier se trouve sur "le bord du disque" et les tete de lecture "au centre"), de son degré de fragmentation éventuelle, de la rapidité de rotation du disque, de sa disponibilité ou non dans un cache quelconque, d'un acces "direct" au fichier (il est physiquement sur le disque dur de l'ordinateur au départ duquel on tente d'y accéder) ou non, des autres acces au disque nécessités par d'autres applications...

    Ensuite, de fait, cela peut etre du au programme lui-même, mais, en tout état de cause, tu ne dois pas te baser sur "la premiere lecture" du fichier en question...

    Il y a fort à parier que, si tu faisait une boucle qui appelle la lecture totale du fichier, et que tu l'appelais un nombre suffisant de fois, tu verrais un "temps de lecture moyen" tres largement inférieur, meme en utilisant le meme compilateur...

    Enfin, il n'est pas exclu qu'un compilateur puisse créer un code exécutable plus "propre" ou "plus efficace" qu'un autre... mais là, encore une fois, il faudrait faire une batterie de tests, dans des conditions similaires, pour s'en assurer...

    Sois aussi attentif au fait que, dans les 5 secondes, tu ne précise pas si le temps de (re)compliation ou le délais entre la (re)compilation et le lancement effectif de l'application sont comptés...

    Enfin, il faut être particulièrement prudent... S'agit-t-il d'un "délais estimé" ou d'un délais calculé précisément (parfois, une seconde, ca parrait vraiment long )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par toxcct
    la meilleure facon de comparer les performances, outre de comparer l'assembleur généré,
    Pour des IO, comparer l'assembleur ne me semble pas etre une bonne methode.

    c'est encore de tester...
    C'est mieux que de comparer l'assembleur.

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Quelle est la proportion du temps des IO par rapport au temps de traitement? Parce que meme s'il y a moyen de le faire en 0.005s mais que le temps de traitement derriere est de 4 jours... tu auras gagne 5s sur 4 jours, cad rien.

  9. #9
    Membre émérite

    Profil pro
    Inscrit en
    Avril 2004
    Messages
    219
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2004
    Messages : 219
    Par défaut
    Ce qui m'embête oui c'est ça, c'est que je passe plus de temps à lire le fichier qu'à le traiter.
    Pour un ordre de grandeur :
    - 10 sec de traitement du fichier,
    - 5 sec de lecture,
    - 5 sec de traitement sachant que la fonction split que j'utilise à certains endroits me fait perdre bien 3 sec. (récupérée sur www.codeproject.com)
    en tout cas merci pour tout.
    Je continuerai à chercher mais là j'ai plus trop de temps à perdre là dessus :!

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    moi aussi je trouve que le getline est tres tres lent.
    57000 lignes = 1.7 secondes.

    ce qui doit etre un peu pres comme toi.

    solution: j'ai mappé le fichier en memoire (22 Mo)
    resultat: immediat (0.270 s)

    mais plus de getline

  11. #11
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par TheSeb
    Ce qui m'embête oui c'est ça, c'est que je passe plus de temps à lire le fichier qu'à le traiter.
    Pour un ordre de grandeur :
    - 10 sec de traitement du fichier,
    - 5 sec de lecture,
    - 5 sec de traitement sachant que la fonction split que j'utilise à certains endroits me fait perdre bien 3 sec. (récupérée sur www.codeproject.com)
    en tout cas merci pour tout.
    Je continuerai à chercher mais là j'ai plus trop de temps à perdre là dessus :!
    C'est quoi ton traitement? Utiliser perl ou quelque chose du genre ne serait pas mieux?

    Sinon, passer par la lecture brute (rdbuf()->*get*) plutot que de perdre du temps a construire des strings qui n'ont pas l'air de servir a grand chose.

  12. #12
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par epsilon68
    moi aussi je trouve que le getline est tres tres lent.
    57000 lignes = 1.7 secondes.

    ce qui doit etre un peu pres comme toi.

    solution: j'ai mappé le fichier en memoire (22 Mo)
    resultat: immediat
    Oui mais le contenu n'est pas encore en memoire. Il ne sera mis en memoire qu'a la demande, suivant l'algo du swapper. Ce peut etre un gain si les acces sont consecutifs et que le swapper peut profiter du temps de traitement.

  13. #13
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    j'ai mappé le fichier en memoire:
    j'ai lu le fichier en une seule fois dans un grand char * alloué par new avec la taille du fichier.

    ... pas de swapper

  14. #14
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par epsilon68
    j'ai mappé le fichier en memoire:
    j'ai lu le fichier en une seule fois dans un grand char * alloué par new avec la taille du fichier.

    ... pas de swapper
    Quand je lis "mapper un fichier en memoire", je pense a mmap ou equivalent sous Windows. C'est alors bien le swapper qui intervient pour faire la lecture.

  15. #15
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Je dis peut être une connerie mais on sait jamais.
    Je sais qu'on peut accélérer significativement les entrées/sorties console en C++ avec l'instruction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ios::sync_with_stdio(false);
    Qui désynchronise cout/cin avec printf/scanf. Mais peut-être que ça le fait aussi avec fstream ?

  16. #16
    Invité
    Invité(e)
    Par défaut
    quand bien même cela était vrai (je ne connais pas du tout cette méthode), ça ne fera pas tourner ton disque dur plus vite !
    Dernière modification par Invité ; 27/09/2013 à 19h43.

  17. #17
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par toxcct
    quand bien meme cela etait vrai (je ne connais pas du tout cette méthode), ca ne fera pas tourner ton disque dur plus vite !
    C'est sûr, mais est-on sûr que sa méthode exploite à fond la vitesse de lecture du disque dur ?

  18. #18
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Commence par mettre ton compilateur à jour.
    Les iostreams de MSVC6 sont loin d'être les plus performantes.

  19. #19
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    * La synchronisation de stdin avec stdout n'a rien à voir avecla choucroute
    * Les flux sont effectivement connus pour être moins efficaces que les I/O C. D'un autre côté ils permettent énormément plus de choses : locales localisés, filtrages à la volée, ... Pour des solutions typesafes, rapides, mais bridées, il y a des approches comme celle de FAStreams
    * Tout charger d'un coup peut définitivement être très efficace.

    Bref, quel est le traitement à réaliser sur ces lignes ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  20. #20
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 354
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 354
    Par défaut
    justement, moi je suis en train de realiser un petit outil qui travaille sur des csv et globalement faire un pivot sur les colonnes... (split, std::map etc)

    et ce n'est pas les flux qui sont lents mais les "string"
    d'ailleurs je suis revenu aux char* de loin les plus efficace.

    je mets le fichier dans une zone memoire et je reference les petits bouts de celle-ci par apres. c'est terriblement efficace!!!

    aussi je dois dire que je l'ai fait sur C#, tout bete sans chercher a optimizer,
    et j'ai otenu un temps de 21 s / 90 Mo de memoire.

    le faire pareil en C++ j'obtiens un temps de ~30 s / 300 Mo de memoire
    (utilisation des string et des std::map<string,string> etc)

    avec optimisation : C++ 14 s / 40 Mo de memoire ( 4.5 secondes de traitement, 9.5 s d'ecriture du fichier )
    (mise en memoire du fichier, utilisation des char*, std::map<char*,char*,functor_case_insentive> )

    je vais maintenant faire quelques optimisation de coté c# pour que le benchmark soit equitable....

    J'ai été franchement étonné par C# qui donne de vraiment bons resultats
    sans se soucier de quoi que ce soit .... voila qui donne plutot a reflechir...

    [edit] j'ai meme essayé de le faire avec Qt en pensant que son implicit sharing allait changer du tout au tout ..... laisser tomber il n'y a rien a voir

    [edit2] faire attention a bien ouvrir le fichier en binary sinon il y a des conversion de fin de ligne parfois tres lente (sur Qt ca été flagrant, avec les iostream un peu moins)

    [edit3] j'ai mis les quelques optimisations dans le C# et c'est maintenant 17 s. l'occupation memoire n'a pas changé


    a+

Discussions similaires

  1. Comment mesurer les performances des I/O (lecture d'un fichier XML)?
    Par LGnord dans le forum Tests et Performance
    Réponses: 2
    Dernier message: 08/11/2011, 11h39
  2. PB de performance de lecture d'un fichier :
    Par ksper45 dans le forum Langage
    Réponses: 5
    Dernier message: 28/08/2008, 15h18
  3. Problème de lecture fichier avec std::getline
    Par marcootz dans le forum C++Builder
    Réponses: 13
    Dernier message: 15/05/2008, 15h42
  4. Performance lors de la lecture d'un fichier excel
    Par Acarp47 dans le forum VBA Access
    Réponses: 3
    Dernier message: 29/08/2007, 19h18
  5. [performance] Lecture d'un fichier
    Par Ceylo dans le forum C
    Réponses: 13
    Dernier message: 30/01/2007, 16h07

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