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 :

Même les stations unix peuvent ramer!


Sujet :

C

  1. #1
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut Même les stations unix peuvent ramer!
    Salut à tous, j'ai une petite question concernant les performances d'un programme.

    Je m'explique :

    mon programme, pour l'instant, ne fait rien de plus que lancer une procédure nommée LireLigne, qui lit un nombre de lignes défini d'un document et renvoie un tableau de string.

    Jusqu'ici, c'est super, sauf que quand je le lance pour un fichier qui fait >10 millions de lignes, ça ralentit au fur et à mesure que les lignes sont lues! Donc je me suis dit "c'est à cause de la libération de mémoire que je n'ai pas faite".

    Et apparament je l'ai mal faite, puisque apparament ça ralentit toujours.


    Voici DecoderReseau, dites-lui bonjour et soyez gentil avec lui

    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
    34
    35
    36
    37
    void DecoderReseau()
    {
            char ** donnees;
            char temp[300];
            int i;
            int fini = 0;
            int lignedebut = 0;
            int lignefin = 1000;
            int compteur = 0;
     
     
            do
            {
                    donnees = LireLigne(CHEMINFICHIER_EXTRACTION_MPS, lignedebut, lignefin);
     
                    //traitement, decodage
     
     
     
                    lignedebut = lignefin;
                    lignefin += 1000;
     
     
                    printf("\nbloc %d\n", compteur);
                    compteur++;
     
     
                    //verification de fin de document et liberation memoire
                    for ( i = 0; i < 1000; i ++)
                    {
                            if ( !(strcmp(donnees[i], "#FIN")))fini++;
                            free(donnees[i]);
                            free(donnees);
                    }
            }while (!fini);
     
    }

    et voici LireLigne

    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
    34
    35
    36
    37
    char ** LireLigne(char* nomfichier, int lignedebut, int lignefin)
    {
            int i;
            FILE * fichier;
            char ** donnees = malloc(sizeof(char*)*(1+lignefin-lignedebut));
            char temp[512];
     
            if((fichier = fopen (nomfichier, "r"))!=NULL)
            {
     
                    for (i = 1; i < lignedebut ; i++)
                    {
                            if((fgets(temp, sizeof(temp), fichier))==NULL)break;
                    }
     
                    for (i = 0; i <= (lignefin-lignedebut) ; i++)
                    {
                            if((fgets(temp, sizeof(temp), fichier))!=NULL)
                            {
                                    donnees[i] = (char *)malloc(sizeof(char)*strlen(temp));
                                    strcpy(donnees[i], temp);
                            }
                            else
                            {
                                    donnees[i] = "#FIN";
                            }
                    }
     
                    fclose(fichier);
            }
            else
            {
                    printf("\nFichier introuvable\n");
            }
            return donnees;
     
    }

    pouvez-vous me dire ce que j'ai oublié?



    PS : pour les unixiens, connaissez-vous un moyen de réduire un fichier très gros sans l'ouvrir? j'ai que vi et le fichier est trop gros, je peux pas l'ouvrir

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void DecoderReseau()
    ....
                    for ( i = 0; i < 1000; i ++)
                    {
                            if ( !(strcmp(donnees[i], "#FIN")))fini++;
                            free(donnees[i]);
                            free(donnees);
                    }
    ....
    free(donnees) est fait bien trop tôt : il ne doit être fait qu'après la libération de toutes les donnees[i];
    Qu'est ce qui garantit que 1000, et exactement 1000, donnees[i] ont été allouées ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                    for ( i = 0; i < 1000; i ++)
                    {
                            if ( !(strcmp(donnees[i], "#FIN")))fini++;
                            free(donnees[i]);
                    }
                    free(donnees);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char ** LireLigne(char* nomfichier, int lignedebut, int lignefin)
    .....
                                    donnees[i] = (char *)malloc(sizeof(char)*strlen(temp));
                                    strcpy(donnees[i], temp);
    La zone allouée est trop faible : il n'y a pas la place du zéro terminal placé par strcpy:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    char ** LireLigne(char* nomfichier, int lignedebut, int lignefin)
    .....
                                    donnees[i] = malloc(strlen(temp)+1);
                                    strcpy(donnees[i], temp);

  3. #3
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    C'est exact et c'est bien vu. Néanmoins ça ralentit toujours

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Probablement, ceci est lié à l'allocation mémoire et/ou à la recopie.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    donnees[i] = (char *)malloc(sizeof(char)*strlen(temp));
    strcpy(donnees[i], temp);
    Il faudrait le confirmer en essayant en supprimant les deux lignes et voir si le phénomène continue.

    Si c'est lié à ces lignes, il faudra modifier le code pour s'en débarrasser.

  5. #5
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    en l'occurence je ne peux pas trop me passer de cette architecture (j'ai une dizaine de .c qui sont construits pour utiliser lireligne).

    De plus, ce ne sont pas les deux lignes dont tu parles qui sont incriminées. Je n'ai vraiment aucune idée de ce que cela pourrait être. Ce n'est pas leur faute puisque lorsque je les mets en commentaire et les free en commentaire aussi, ça fait pareil et ça relentit tout autant.

    je vais essayer de faire des tests autre part, mais je pars la mort dans l'âme... ça me scie en deux de savoir que je perds une après-midi sur un détail comme ça.

  6. #6
    Membre émérite
    Inscrit en
    Juillet 2005
    Messages
    512
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 512
    Par défaut
    Dans la fonction LireLigne cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                    for (i = 1; i < lignedebut ; i++)
                    {
                            if((fgets(temp, sizeof(temp), fichier))==NULL)break;
                    }
    va être de plus en plus longue à exécuter car lignedebut est de plus en plus grand au fur et à mesure que tu avance dans l'exécution de ton prog.

  7. #7
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Par défaut
    Exactement ! Et c'est la un gros problème de conception !!

    C'est pas la station unix qui rame, mais le code applicatif qui est trés trés mal pensé ! (voir même masochiste en terme de perf !)

    Citation Envoyé par Lucien63 Voir le message
    Dans la fonction LireLigne cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                    for (i = 1; i < lignedebut ; i++)
                    {
                            if((fgets(temp, sizeof(temp), fichier))==NULL)break;
                    }
    va être de plus en plus longue à exécuter car lignedebut est de plus en plus grand au fur et à mesure que tu avance dans l'exécution de ton prog.
    Vincent Rogier.

    Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

    Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

    OCILIB (C Driver for Oracle)

    Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle

  8. #8
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    vaudrait-il mieux que je fasse un compteur qui s'incrémente à chaque fois que je lis un caractère \n? ou alors que je groupe tout en un seul morceau? si je choisi cette solution la ram ne tiendra pas, c'est sûr.

    ou alors devrais-je augmenter l'inervalle de lecture (au lieu de faire 1000 lignes par 1000 lignes, ça serait 100 000 par 100 000)?

    comment auriez-vous pensé à ma place? comment auriez-vous envisagé l'algo?

  9. #9
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    ...... ou alors ouvrir mon fichier dans le programme appelant et traiter ligne par ligne. pourquoi n'y ai-je pas pensé plus tôt...





    quoi qu'il en soit, je vais être confronté au même problème dans d'autres fonctions. je repose donc ma question du post d'avant. Comment auriez-vous pensé cette démarche?

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    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 392
    Par défaut
    Citation Envoyé par Lucien63 Voir le message
    Dans la fonction LireLigne cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
                    for (i = 1; i < lignedebut ; i++)
                    {
                            if((fgets(temp, sizeof(temp), fichier))==NULL)break;
                    }
    va être de plus en plus longue à exécuter car lignedebut est de plus en plus grand au fur et à mesure que tu avance dans l'exécution de ton prog.
    Ça me rappelle un article du Daily WTF, ça...
    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.

  11. #11
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par crashtib Voir le message
    quoi qu'il en soit, je vais être confronté au même problème dans d'autres fonctions. je repose donc ma question du post d'avant. Comment auriez-vous pensé cette démarche?
    je ferais des ftell / fseek


Discussions similaires

  1. Verrou empechant même les select
    Par ilalaina dans le forum Administration
    Réponses: 11
    Dernier message: 03/10/2007, 15h55
  2. Réponses: 3
    Dernier message: 16/06/2007, 19h47
  3. Réponses: 9
    Dernier message: 14/06/2007, 12h22
  4. Réponses: 2
    Dernier message: 16/12/2006, 19h00

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