Annotation of rpl/src/profilage.c, revision 1.1

1.1     ! bertrand    1: /*
        !             2: ================================================================================
        !             3:   RPL/2 (R) version 4.0.9
        !             4:   Copyright (C) 1989-2010 Dr. BERTRAND Joël
        !             5: 
        !             6:   This file is part of RPL/2.
        !             7: 
        !             8:   RPL/2 is free software; you can redistribute it and/or modify it
        !             9:   under the terms of the CeCILL V2 License as published by the french
        !            10:   CEA, CNRS and INRIA.
        !            11:  
        !            12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
        !            13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
        !            14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
        !            15:   for more details.
        !            16:  
        !            17:   You should have received a copy of the CeCILL License
        !            18:   along with RPL/2. If not, write to info@cecill.info.
        !            19: ================================================================================
        !            20: */
        !            21: 
        !            22: 
        !            23: #include "rpl.conv.h"
        !            24: 
        !            25: 
        !            26: /*
        !            27: ================================================================================
        !            28:   Fonction de profilage
        !            29: ================================================================================
        !            30:   Entrées : pointeur sur une structure processus
        !            31: --------------------------------------------------------------------------------
        !            32:   Sorties :
        !            33: --------------------------------------------------------------------------------
        !            34:   Effets de bord : néant
        !            35: ================================================================================
        !            36: */
        !            37: 
        !            38: // Si *fonction est non nul, profilage considère un appel à la fonction
        !            39: // *fonction. Si *fonction est nul, il s'agit du retour de la fonction.
        !            40: 
        !            41: void
        !            42: profilage(struct_processus *s_etat_processus, unsigned char *fonction)
        !            43: {
        !            44:    struct_liste_profilage      *l_element_cible;
        !            45:    struct_liste_profilage      *l_element_courant;
        !            46:    struct_liste_profilage2     *l_element_fonction;
        !            47: 
        !            48:    struct timeval              horodatage;
        !            49:    struct timeval              temps;
        !            50: 
        !            51:    /*
        !            52:     * Les statistiques sont écrites dans un fichier rpl-profile-pid-tid
        !            53:     * à chaque minute.
        !            54:     */
        !            55: 
        !            56:    gettimeofday(&horodatage, NULL);
        !            57: 
        !            58:    if (fonction != NULL)
        !            59:    {
        !            60:        /*
        !            61:         * Recherche d'une occurrence de l'appel de la fonction
        !            62:         * et arrêt du compteur de la fonction appelante
        !            63:         */
        !            64: 
        !            65:        l_element_courant = (*s_etat_processus).pile_profilage;
        !            66:        l_element_cible = NULL;
        !            67: 
        !            68:        while(l_element_courant != NULL)
        !            69:        {
        !            70:            if (strcmp((*l_element_courant).fonction, fonction) == 0)
        !            71:            {
        !            72:                l_element_cible = l_element_courant;
        !            73:            }
        !            74: 
        !            75:            if ((*s_etat_processus).pile_profilage_fonctions != NULL)
        !            76:            {
        !            77:                if (strcmp((*l_element_courant).fonction,
        !            78:                        (*(*s_etat_processus).pile_profilage_fonctions)
        !            79:                        .fonction) == 0)
        !            80:                {
        !            81:                    if (horodatage.tv_usec < (*l_element_courant)
        !            82:                            .dernier_appel.tv_usec)
        !            83:                    {
        !            84:                        // Avec retenue
        !            85:                        temps.tv_usec = (1000000 + horodatage.tv_usec)
        !            86:                                - (*l_element_courant).dernier_appel.tv_usec;
        !            87:                        temps.tv_sec = horodatage.tv_sec
        !            88:                                - ((*l_element_courant).dernier_appel.tv_sec
        !            89:                                + 1);
        !            90:                    }
        !            91:                    else
        !            92:                    {
        !            93:                        // Sans retenue
        !            94:                        temps.tv_usec = horodatage.tv_usec
        !            95:                                - (*l_element_courant).dernier_appel.tv_usec;
        !            96:                        temps.tv_sec = horodatage.tv_sec
        !            97:                                - (*l_element_courant).dernier_appel.tv_sec;
        !            98:                    }
        !            99: 
        !           100:                    // Cumul
        !           101: 
        !           102:                    (*l_element_courant).cumul.tv_usec += temps.tv_usec;
        !           103:                    (*l_element_courant).cumul.tv_sec += temps.tv_sec;
        !           104: 
        !           105:                    if ((*l_element_courant).cumul.tv_usec >= 1000000)
        !           106:                    {
        !           107:                        (*l_element_courant).cumul.tv_usec -= 1000000;
        !           108:                        (*l_element_courant).cumul.tv_sec++;
        !           109:                    }
        !           110:                }
        !           111:            }
        !           112: 
        !           113:            l_element_courant = (*l_element_courant).suivant;
        !           114:        }
        !           115: 
        !           116:        l_element_courant = l_element_cible;
        !           117: 
        !           118:        if (l_element_courant == NULL)
        !           119:        {
        !           120:            // Nouvel appel
        !           121: 
        !           122:            if ((l_element_courant = malloc(sizeof(struct_liste_profilage)))
        !           123:                    == NULL)
        !           124:            {
        !           125:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           126:                return;
        !           127:            }
        !           128: 
        !           129:            (*l_element_courant).suivant = (*s_etat_processus).pile_profilage;
        !           130:            (*s_etat_processus).pile_profilage = l_element_courant;
        !           131: 
        !           132:            if (((*l_element_courant).fonction = malloc((strlen(fonction) + 1) *
        !           133:                    sizeof(unsigned char))) == NULL)
        !           134:            {
        !           135:                (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           136:                return;
        !           137:            }
        !           138: 
        !           139:            strcpy((*l_element_courant).fonction, fonction);
        !           140: 
        !           141:            (*l_element_courant).cumul.tv_sec = 0;
        !           142:            (*l_element_courant).cumul.tv_usec = 0;
        !           143:            (*l_element_courant).nombre_appels = 0;
        !           144:        }
        !           145: 
        !           146:        (*l_element_courant).dernier_appel = horodatage;
        !           147:        (*l_element_courant).nombre_appels++;
        !           148: 
        !           149:        // Empilement
        !           150: 
        !           151:        if ((l_element_fonction = malloc(sizeof(struct_liste_profilage2)))
        !           152:                == NULL)
        !           153:        {
        !           154:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           155:            return;
        !           156:        }
        !           157: 
        !           158:        if (((*l_element_fonction).fonction = malloc((strlen(fonction) + 1) *
        !           159:                sizeof(unsigned char))) == NULL)
        !           160:        {
        !           161:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           162:            return;
        !           163:        }
        !           164: 
        !           165:        strcpy((*l_element_fonction).fonction, fonction);
        !           166:        (*l_element_fonction).suivant = (*s_etat_processus)
        !           167:                .pile_profilage_fonctions;
        !           168:        (*s_etat_processus).pile_profilage_fonctions = l_element_fonction;
        !           169:    }
        !           170:    else
        !           171:    {
        !           172:        if ((*s_etat_processus).pile_profilage_fonctions == NULL)
        !           173:        {
        !           174:            (*s_etat_processus).erreur_execution = d_ex_erreur_profilage;
        !           175:            return;
        !           176:        }
        !           177: 
        !           178:        l_element_courant = (*s_etat_processus).pile_profilage;
        !           179: 
        !           180:        while(l_element_courant != NULL)
        !           181:        {
        !           182:            if (strcmp((*l_element_courant).fonction,
        !           183:                    (*(*s_etat_processus).pile_profilage_fonctions).fonction)
        !           184:                    == 0)
        !           185:            {
        !           186:                break;
        !           187:            }
        !           188: 
        !           189:            l_element_courant = (*l_element_courant).suivant;
        !           190:        }
        !           191: 
        !           192:        BUG(l_element_courant == NULL, printf("Function %s not found!\n",
        !           193:                (*(*s_etat_processus).pile_profilage_fonctions).fonction));
        !           194: 
        !           195:        // Soustraction des temps
        !           196: 
        !           197:        if (horodatage.tv_usec < (*l_element_courant).dernier_appel.tv_usec)
        !           198:        {
        !           199:            // Avec retenue
        !           200:            temps.tv_usec = (1000000 + horodatage.tv_usec)
        !           201:                    - (*l_element_courant).dernier_appel.tv_usec;
        !           202:            temps.tv_sec = horodatage.tv_sec
        !           203:                    - ((*l_element_courant).dernier_appel.tv_sec + 1);
        !           204:        }
        !           205:        else
        !           206:        {
        !           207:            // Sans retenue
        !           208:            temps.tv_usec = horodatage.tv_usec
        !           209:                    - (*l_element_courant).dernier_appel.tv_usec;
        !           210:            temps.tv_sec = horodatage.tv_sec
        !           211:                    - (*l_element_courant).dernier_appel.tv_sec;
        !           212:        }
        !           213: 
        !           214:        // Cumul
        !           215: 
        !           216:        (*l_element_courant).cumul.tv_usec += temps.tv_usec;
        !           217:        (*l_element_courant).cumul.tv_sec += temps.tv_sec;
        !           218: 
        !           219:        if ((*l_element_courant).cumul.tv_usec >= 1000000)
        !           220:        {
        !           221:            (*l_element_courant).cumul.tv_usec -= 1000000;
        !           222:            (*l_element_courant).cumul.tv_sec++;
        !           223:        }
        !           224: 
        !           225:        // Dépilement
        !           226: 
        !           227:        l_element_fonction = (*s_etat_processus).pile_profilage_fonctions;
        !           228:        (*s_etat_processus).pile_profilage_fonctions =
        !           229:                (*l_element_fonction).suivant;
        !           230: 
        !           231:        free((*l_element_fonction).fonction);
        !           232:        free(l_element_fonction);
        !           233: 
        !           234:        // Relance du compteur de la fonction en cours
        !           235: 
        !           236:        if ((*s_etat_processus).pile_profilage_fonctions != NULL)
        !           237:        {
        !           238:            l_element_courant = (*s_etat_processus).pile_profilage;
        !           239: 
        !           240:            while(l_element_courant != NULL)
        !           241:            {
        !           242:                if (strcmp((*l_element_courant).fonction, (*(*s_etat_processus)
        !           243:                        .pile_profilage_fonctions).fonction) == 0)
        !           244:                {
        !           245:                    break;
        !           246:                }
        !           247: 
        !           248:                l_element_courant = (*l_element_courant).suivant;
        !           249:            }
        !           250: 
        !           251:            BUG(l_element_courant == NULL, printf("Function %s not found!\n",
        !           252:                    (*(*s_etat_processus).pile_profilage_fonctions).fonction));
        !           253:            (*l_element_courant).dernier_appel = horodatage;
        !           254:        }
        !           255:    }
        !           256: 
        !           257:    if ((horodatage.tv_sec - (*s_etat_processus).horodatage_profilage.tv_sec)
        !           258:            >= 60)
        !           259:    {
        !           260:        ecriture_profil(s_etat_processus);
        !           261:        (*s_etat_processus).horodatage_profilage = horodatage;
        !           262:    }
        !           263: 
        !           264:    return;
        !           265: }
        !           266: 
        !           267: void
        !           268: ecriture_profil(struct_processus *s_etat_processus)
        !           269: {
        !           270:    double                      fraction;
        !           271:    double                      temps;
        !           272:    double                      total;
        !           273: 
        !           274:    file                        *fichier;
        !           275: 
        !           276:    struct_liste_profilage      *l_element_courant;
        !           277: 
        !           278:    struct timeval              cumul;
        !           279: 
        !           280:    unsigned char               *nom;
        !           281: 
        !           282:    l_element_courant = (*s_etat_processus).pile_profilage;
        !           283: 
        !           284:    // Calcul du temps total
        !           285: 
        !           286:    cumul.tv_sec = 0;
        !           287:    cumul.tv_usec = 0;
        !           288: 
        !           289:    while(l_element_courant != NULL)
        !           290:    {
        !           291:        cumul.tv_usec += (*l_element_courant).cumul.tv_usec;
        !           292:        cumul.tv_sec += (*l_element_courant).cumul.tv_sec;
        !           293: 
        !           294:        if (cumul.tv_usec >= 1000000)
        !           295:        {
        !           296:            cumul.tv_usec -= 1000000;
        !           297:            cumul.tv_sec++;
        !           298:        }
        !           299: 
        !           300:        l_element_courant = (*l_element_courant).suivant;
        !           301:    }
        !           302: 
        !           303:    total = cumul.tv_sec + (((double) cumul.tv_usec) / 1000000);
        !           304: 
        !           305:    // Création du fichier
        !           306: 
        !           307:    if ((nom = malloc((strlen(ds_rplprofile) + 64 + 1) * sizeof(unsigned char)))
        !           308:            == NULL)
        !           309:    {
        !           310:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
        !           311:        return;
        !           312:    }
        !           313: 
        !           314:    snprintf(nom, strlen(ds_rplprofile) + 64 + 1,
        !           315:            "%s-%lu-%lu", ds_rplprofile, (unsigned long) getpid(),
        !           316:            (unsigned long) pthread_self());
        !           317: 
        !           318:    if ((fichier = fopen(nom, "w+")) == NULL)
        !           319:    {
        !           320:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           321:        free(nom);
        !           322: 
        !           323:        return;
        !           324:    }
        !           325: 
        !           326:    free(nom);
        !           327: 
        !           328:    // Préparation du résultat
        !           329: 
        !           330:    if (fprintf(fichier, "RPL/2 statistics\n\n") < 0)
        !           331:    {
        !           332:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           333:        return;
        !           334:    }
        !           335: 
        !           336:    if (fprintf(fichier, "Process      : %lu\n", (unsigned long)
        !           337:                getpid()) < 0)
        !           338:    {
        !           339:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           340:        return;
        !           341:    }
        !           342: 
        !           343:    if (fprintf(fichier, "Thread       : %lu\n", (unsigned long)
        !           344:                pthread_self()) < 0)
        !           345:    {
        !           346:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           347:        return;
        !           348:    }
        !           349: 
        !           350:    if (fprintf(fichier, "Elapsed Time : %.2fs\n\n", total) < 0)
        !           351:    {
        !           352:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           353:        return;
        !           354:    }
        !           355: 
        !           356:    if (fprintf(fichier, "Calls_________ Time____________  Ratio__ Normal_ "
        !           357:            "   Object______________________\n") < 0)
        !           358:    {
        !           359:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           360:        return;
        !           361:    }
        !           362: 
        !           363:    l_element_courant = (*s_etat_processus).pile_profilage;
        !           364: 
        !           365:    while(l_element_courant != NULL)
        !           366:    {
        !           367:        temps = (*l_element_courant).cumul.tv_sec +
        !           368:                (((double) (*l_element_courant).cumul.tv_usec) / 1000000);
        !           369:        fraction = 100 * (temps / total);
        !           370: 
        !           371:        if (fprintf(fichier, "<%012lld> %15.2fs (%6.2f%%/%6.2f%%) : %s\n",
        !           372:                (*l_element_courant).nombre_appels,
        !           373:                temps, fraction, fraction / (*l_element_courant).nombre_appels,
        !           374:                (*l_element_courant).fonction) < 0)
        !           375:        {
        !           376:            (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           377:            return;
        !           378:        }
        !           379: 
        !           380:        l_element_courant = (*l_element_courant).suivant;
        !           381:    }
        !           382: 
        !           383:    if (fclose(fichier) != 0)
        !           384:    {
        !           385:        (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
        !           386:        return;
        !           387:    }
        !           388: 
        !           389:    return;
        !           390: }
        !           391: 
        !           392: void
        !           393: liberation_profil(struct_processus *s_etat_processus)
        !           394: {
        !           395:    struct_liste_profilage      *l_element_courant;
        !           396:    struct_liste_profilage2     *l_element_fonction;
        !           397: 
        !           398:    while((*s_etat_processus).pile_profilage != NULL)
        !           399:    {
        !           400:        l_element_courant = (*s_etat_processus).pile_profilage;
        !           401:        (*s_etat_processus).pile_profilage =
        !           402:                (*(*s_etat_processus).pile_profilage).suivant;
        !           403: 
        !           404:        free((*l_element_courant).fonction);
        !           405:        free(l_element_courant);
        !           406:    }
        !           407: 
        !           408:    while((*s_etat_processus).pile_profilage_fonctions != NULL)
        !           409:    {
        !           410:        l_element_fonction = (*s_etat_processus).pile_profilage_fonctions;
        !           411:        (*s_etat_processus).pile_profilage_fonctions =
        !           412:                (*(*s_etat_processus).pile_profilage_fonctions).suivant;
        !           413: 
        !           414:        free((*l_element_fonction).fonction);
        !           415:        free(l_element_fonction);
        !           416:    }
        !           417: 
        !           418:    return;
        !           419: }
        !           420: 
        !           421: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>