File:  [local] / rpl / src / profilage.c
Revision 1.66: download - view: text, annotated - select for diffs - revision graph
Fri Jan 10 11:15:50 2020 UTC (4 years, 3 months ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_32, HEAD
Modification du copyright.

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.32
    4:   Copyright (C) 1989-2020 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 = ((double) 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-%llu-%llu", ds_rplprofile, (unsigned long long) getpid(),
  316:             (unsigned long 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      : %llu\n", (unsigned long long)
  337:                 getpid()) < 0)
  338:     {
  339:         (*s_etat_processus).erreur_systeme = d_es_erreur_fichier;
  340:         return;
  341:     }
  342: 
  343:     if (fprintf(fichier, "Thread       : %llu\n", (unsigned long 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 = ((double) (*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, temps, fraction,
  373:                 fraction / ((double) (*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>