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

1.1       bertrand    1: /*
                      2: ================================================================================
1.22    ! bertrand    3:   RPL/2 (R) version 4.1.0.prerelease.3
1.15      bertrand    4:   Copyright (C) 1989-2011 Dr. BERTRAND Joël
1.1       bertrand    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: 
1.11      bertrand   23: #include "rpl-conv.h"
1.1       bertrand   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>