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

C Discussion :

[performance] Lecture d'un fichier


Sujet :

C

  1. #1
    Membre émérite Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Par défaut [performance] Lecture d'un fichier
    Bonjour,

    Je développe actuellement un programme de coloriage (voir http://developpez.net/forums/showthread.php?t=267010).

    J'ai fait quelques test pour voir un peu les performances sur de plus gros fichiers, afin d'optimiser mon programme. Et lors de la lecture d'un fichier plus gros, je dois attendre très très longtemps (plusieurs minutes voir plusieurs dizaines de minutes selon la taille du fichier (1 Mo/8 Mo)).

    Je sais bien que c'est plutôt rare ou même inexistant des codes en C de plusieurs Mo, mais mon soucis et d'avoir pour de prochains programmes, des fonctions de lecture efficaces (puisque ma fonction d'écriture a déjà de bonnes performances).

    Voila ce que j'utilise (je tiens à utiliser uniquement des fichiers d'en-tête standards pour la portabilité du code) :

    Code C : 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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    #include <stdlib.h>
    #include <string.h>
     
    [...]
     
    // pour l'assemblage des chaines de caractères
    char *str_cat (char *str1, char const *str2)
    {
    	if ((str1 == NULL) && (str2 == NULL))
    		return NULL;
    	if (str1 == NULL)
    		return strdup (str2);
    	if (str2 == NULL)
    		return str1;
     
    	char *strCat = NULL;
    	size_t len1;
    	if (str1 == NULL)
    		len1 = 0;
    	else
    		len1 = strlen (str1);
     
    	void *tmp = realloc (str1, len1 + strlen (str2) + 1);
     
    	if (tmp != NULL)
    	{
    		strCat = tmp;
    		if (str1 == NULL)
    		{
    			strcpy (strCat, "");
    		}
    		strcat (strCat, str2);
    	}
    	else
    	{
    		free (strCat), strCat = NULL;
    	}
     
    	return strCat;
    }
     
    // et la fonction de lecture du fichier...
    char *readFromFile (const char *path)
    {
    	char *cData = NULL;
    	FILE *fichier = fopen (path, "r");
     
    	if (fichier != NULL)
    	{
    		char chaine[BUFSIZ];
    		unsigned long lines = 0;
    		while (fgets (chaine, sizeof chaine, fichier) != NULL)
    		{
    			cData = str_cat (cData, chaine);
    			if (cData == NULL)
    			{
    				puts ("Erreur de memoire");
    				break;
    			}
    			lines++;
    		}
    		fclose (fichier);
    	}
     
    	return cData;
    }

    Merci d'avance et bon développement à tous

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je dirais que tu fais trop de réallocations, car tu réalloues à chaque fois "la bonne taille".

    Mon conseil, c'est de réserver une taille supérieure, mémoriser cette taille et ne réallouer que quand la taille est atteinte.
    Pour la réallocation, une bonne méthode peut être de multiplier la taille du buffer par un coefficient fixe, genre 1.5 (un rapport inférieur au nombre d'or est conseillé, pour une raison dont je n'ai plus les détails).

    Ou bien, tu peux tenter la technique de la FAQ pour connaître la taille du fichier, et allouer ta mémoire d'un coup. Seulement, ça ne marchera que sur un vrai fichier (pas un fifo par exemple) et il y a souvent des problèmes pour les fichiers ouverts en mode texte.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre émérite Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Par défaut
    Et… n'y a-t-il pas un moyen d'obtenir directement le nombre de caractères composant le fichier, puis d'allouer directement la taille correspondante et tout y mettre d'un coup ?

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par Spootnik-Dev
    Et… n'y a-t-il pas un moyen d'obtenir directement le nombre de caractères composant le fichier, puis d'allouer directement la taille correspondante et tout y mettre d'un coup ?
    Lire le fichier caractère pas caractère et de les compter en même temps, du moins c'est ce que je fairais

    Une autre solution consisterais à utiliser stat, il se trouve que cette structure possède un champ st_size qui permet de récupérer la taille totale d'un fichier en octets. C'est du POSIX donc ca reste portable !
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    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 Médinoc
    Pour la réallocation, une bonne méthode peut être de multiplier la taille du buffer par un coefficient fixe, genre 1.5 (un rapport inférieur au nombre d'or est conseillé, pour une raison dont je n'ai plus les détails).
    Pour ceux-ci, voir: http://www.bourguet.org/realloc.pdf

  6. #6
    Membre éprouvé
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Par défaut
    Citation Envoyé par Spootnik-Dev
    Et… n'y a-t-il pas un moyen d'obtenir directement le nombre de caractères composant le fichier, puis d'allouer directement la taille correspondante et tout y mettre d'un coup ?
    ouaipe, un coup de fseek et un ftell ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    FILE* myfile = fopen(...);
    long len;
    char *data=NULL;
    /*j'omet volontairement les tests usuels
    a faire apres un fopen*/
          fseek (myfile, 0L, SEEK_END);
          len = ftell (myfile);
          data = malloc (len);
    //rewind(myfile);
          fseek (myfile, 0L, SEEK_SET);
          fread (data, 1, len, myfile);
    je precise que le code est a completer avec tous les tests d'usage (echec de fopen?, echec de malloc? ...)

    -edit-
    code deja present dans la FAQ: http://c.developpez.com/faq/c/?page=...HIERS_filesize

  7. #7
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Citation Envoyé par Franck.H
    [...] utiliser stat [...]
    Ou fstat()

    @Spootnik-Dev : est-ce que j'ai mal lu ou est-ce que tu lis tron fichier ligne par ligne pour finalement le mettre entièrement dans un buffer ?
    Si j'ai bien lu, il n'y a pas que les réallocations qui te font perdre du temps...

    Personnellement, je ferai :
    - soit fopen() + fstat() + malloc() + fread() + fclose()
    - soit malloc() + fopen() + tant que pas tout lu { fread() + realloc() si besoin avec progression geometrique } + fclose()

    L'avantage de la deuxième méthode étant qu'elle fonctionne aussi avec les fifo.

  8. #8
    Membre émérite Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Par défaut
    Citation Envoyé par David.Schris
    L'avantage de la deuxième méthode étant qu'elle fonctionne aussi avec les fifo.
    Les fifo ??? qu'est-ce que c'est que ça ? désolé si mes questions vous paraissent étrange, je ne suis pas encore très à l'aise dans la manipulation des fichiers.

  9. #9
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Ce sont des fichiers un peu spéciaux qui sont surtout utilisé pour la communication inter processus, les Pipes (ou tubes) pour être plus exacte.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  10. #10
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Citation Envoyé par Spootnik-Dev
    Les fifo ??? qu'est-ce que c'est que ça ? désolé si mes questions vous paraissent étrange, je ne suis pas encore très à l'aise dans la manipulation des fichiers.
    FIFO : First In First Out.
    Imagine un tube (cylindrique) et des balles (sphériques) dont le diamètre leur permet de rentrer tout juste dans le tube. Tiens (par la pensée [1], puisque tu imagines) le tube horizontalement et mets les balles dedans en les faisant toutes entrer par la même extrémité. Penche le tube de façon à ce que l'extrémité par laquelle les balles ont été entrées soit plus haute que l'autre : la première balle mise dans le tube est la première à sortir. Magique !
    Dans la série, il y a LIFO (ou FILO) : Last In First Out. C'est une pile (comme dans "empiler", pas comme dans la pub avec les lapins).
    Certains excentriques parleraient de FINO (First In Never Out ?) mais à mon avis, c'est pas "fino"...

    Aussi, voir http://man.developpez.com/man1/mkfifo.1.php

    [1] - Que la force soit avec toi

  11. #11
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par Spootnik-Dev
    [CODE=C]
    char *str_cat (char *str1, char const *str2)
    {
    void *tmp = realloc (str1, len1 + strlen (str2) + 1);

    <...>
    return strCat;
    }
    Il ne faut pas réallouer à chaque appel. J'ai résolu ce problème avec un TAD 'FSTR' (Flexible STRing).

    http://emmanuel-delahaye.developpez.com/clib.htm
    Module FSTR

  12. #12
    Membre émérite Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    J'ai résolu ce problème avec un TAD 'FSTR' (Flexible STRing).
    Elle m'a l'air super ta bibliothèque, je teste dès que j'ai le temps, là je suis crevé .

    PS: merci beaucoup aussi aux autres personnes qui m'ont aidées

  13. #13
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Citation Envoyé par Spootnik-Dev
    Mon site disponible de 8h à 21h GTM en semaine et de 13h à 21h GTM le week-end
    "GTM" ou "GMT" ?

  14. #14
    Membre émérite Avatar de Ceylo
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2007
    Messages
    1 216
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 216
    Par défaut
    euh… oui GMT, tu as raison

Discussions similaires

  1. Performances en lecture d'un fichier (std::getline)
    Par TheSeb dans le forum SL & STL
    Réponses: 29
    Dernier message: 13/07/2012, 00h16
  2. Performance lecture fichier
    Par MatRem dans le forum Général Python
    Réponses: 8
    Dernier message: 04/12/2011, 03h10
  3. 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
  4. PB de performance de lecture d'un fichier :
    Par ksper45 dans le forum Langage
    Réponses: 5
    Dernier message: 28/08/2008, 15h18
  5. 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

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