src/core/stats.c

Go to the documentation of this file.
00001 
00008 #include <string.h>
00009 #include <core/tx.h>
00010 #include <core/txdesc.h>
00011 #include <core/stats.h>
00012 #include <core/config.h>
00013 #include <misc/hash_table.h>
00014 #include <misc/generic_types.h>
00015 #include <misc/malloc.h>
00016 #include <misc/mutex.h>
00017 #include <misc/debug.h>
00018 
00019 txc_statsmgr_t *txc_g_statsmgr;
00020 
00021 #define MIN(A, B) (((A) < (B)) ? (A) : (B))
00022 #define MAX(A, B) (((A) > (B)) ? (A) : (B))
00023 
00024 #define ACTION(name) #name,
00025 char *stats_strings[] = {
00026         FOREACH_STAT(ACTION)
00027 };      
00028 #undef ACTION   
00029 
00030 static const char __whitespaces[] = "                                                              ";
00031 
00032 #define WHITESPACE(len) &__whitespaces[sizeof(__whitespaces) - (len) -1]
00033 
00035 struct txc_stats_threadstat_s {
00036         txc_stats_statcounter_t       count;     
00037         txc_stats_stat_t              total_stats[txc_stats_numofstats]; 
00038         txc_hash_table_t              *tx_stats; 
00039         struct txc_stats_threadstat_s *next;     
00040         struct txc_stats_threadstat_s *prev;     
00041         txc_tx_t                      *txd;      
00042 };
00043 
00044 
00046 struct txc_statsmgr_s {
00047         txc_mutex_t            mutex;                       
00048         unsigned int           alloc_threadstat_num;        
00049         txc_stats_threadstat_t *alloc_threadstat_list_head; 
00050         txc_stats_threadstat_t *alloc_threadstat_list_tail; 
00051 };
00052 
00053 
00054 txc_result_t
00055 txc_statsmgr_create(txc_statsmgr_t **statsmgrp)
00056 {
00057         *statsmgrp = (txc_statsmgr_t *) MALLOC(sizeof(txc_statsmgr_t));
00058         if (*statsmgrp == NULL) {
00059                 return TXC_R_NOMEMORY;
00060         }
00061 
00062         (*statsmgrp)->alloc_threadstat_num = 0;
00063         (*statsmgrp)->alloc_threadstat_list_head = (*statsmgrp)->alloc_threadstat_list_tail = NULL;
00064         TXC_MUTEX_INIT(&(*statsmgrp)->mutex, NULL);
00065 
00066         return TXC_R_SUCCESS;
00067 }
00068 
00069 
00070 txc_result_t
00071 txc_statsmgr_destroy(txc_statsmgr_t **statsmgrp)
00072 {
00073         txc_stats_threadstat_t *threadstat;
00074         txc_stats_threadstat_t *threadstat_next;
00075         txc_statsmgr_t         *statsmgr = *statsmgrp;
00076 
00077 
00078         for (threadstat=statsmgr->alloc_threadstat_list_head;
00079              threadstat != NULL;
00080                  threadstat = threadstat_next)
00081         {
00082                 threadstat_next = threadstat->next;
00083                 FREE(threadstat);
00084         }
00085 
00086         FREE(statsmgr);
00087         *statsmgrp = NULL;
00088 
00089         return TXC_R_SUCCESS;
00090 }
00091 
00092 
00093 txc_result_t
00094 txc_stats_threadstat_create(txc_statsmgr_t *statsmgr, 
00095                             txc_stats_threadstat_t **threadstatp,
00096                             txc_tx_t *txd)
00097 {
00098         txc_stats_threadstat_t *threadstat;
00099         int                    i;
00100 
00101         threadstat = (txc_stats_threadstat_t *) MALLOC(sizeof(txc_stats_threadstat_t));
00102 
00103         TXC_MUTEX_LOCK(&(statsmgr->mutex));
00104         if (statsmgr->alloc_threadstat_list_head == NULL) {
00105                 TXC_ASSERT(statsmgr->alloc_threadstat_list_tail == NULL);
00106                 statsmgr->alloc_threadstat_list_head = threadstat;
00107                 statsmgr->alloc_threadstat_list_tail = threadstat;
00108                 threadstat->next = NULL;
00109                 threadstat->prev = NULL;
00110         } else {
00111                 statsmgr->alloc_threadstat_list_tail->next = threadstat;
00112                 threadstat->prev = statsmgr->alloc_threadstat_list_tail;
00113                 statsmgr->alloc_threadstat_list_tail = threadstat;
00114         }
00115         statsmgr->alloc_threadstat_num++;
00116         TXC_MUTEX_UNLOCK(&(statsmgr->mutex));
00117 
00118         threadstat->count = 0;                                    
00119         threadstat->txd = txd;
00120         txc_hash_table_create(&threadstat->tx_stats, 
00121                               TXC_STATS_THREADSTAT_HASHTABLE_SIZE, 
00122                                                   TXC_BOOL_FALSE);
00123         for (i=0; i<txc_stats_numofstats; i++) {
00124                 threadstat->total_stats[i].total = 0;
00125                 threadstat->total_stats[i].min       = 0xFFFFFFFF;
00126                 threadstat->total_stats[i].max       = 0;
00127         }       
00128 
00129         *threadstatp = threadstat;
00130         return TXC_R_SUCCESS;                                     
00131 }
00132 
00133 
00134 txc_result_t
00135 txc_stats_txstat_create(txc_stats_txstat_t **txstatp)
00136 {
00137         txc_stats_txstat_t *txstat;
00138 
00139         txstat = (txc_stats_txstat_t *) MALLOC(sizeof(txc_stats_txstat_t));
00140         txstat->count = 0;
00141         *txstatp = txstat;
00142 
00143         return TXC_R_SUCCESS;                                     
00144 }
00145 
00146 
00147 txc_result_t
00148 txc_stats_txstat_destroy(txc_stats_txstat_t **txstatp)
00149 {
00150         FREE(*txstatp);
00151         *txstatp = NULL;
00152 
00153         return TXC_R_SUCCESS;                                     
00154 }
00155 
00156 
00157 static
00158 void
00159 stats_txstat_reset(txc_stats_txstat_t *txstat)
00160 {
00161 #define RESETSTAT(name)                                                      \
00162   txstat->total_stats[txc_stats_##name##_stat].total = 0;                    \
00163   txstat->total_stats[txc_stats_##name##_stat].min = 0xFFFFFFFF;             \
00164   txstat->total_stats[txc_stats_##name##_stat].max = 0;
00165 
00166         FOREACH_STAT (RESETSTAT)
00167 
00168 #undef RESETSTAT        
00169 }
00170 
00171 
00172 txc_result_t
00173 txc_stats_txstat_init(txc_stats_txstat_t *txstat, 
00174                       const char *srcloc_str, 
00175                       txc_tx_srcloc_t *srcloc)
00176 {
00177         if (txc_runtime_settings.statistics == TXC_BOOL_TRUE) {
00178                 txstat->count = 1;
00179                 txstat->srcloc_str = srcloc_str;
00180                 txstat->srcloc.line = srcloc->line;
00181                 txstat->srcloc.fun = srcloc->fun;
00182                 txstat->srcloc.file = srcloc->file;
00183                 stats_txstat_reset(txstat);
00184         }
00185         return TXC_R_SUCCESS;
00186 }
00187 
00188 
00189 static
00190 void
00191 stats_get_txstat_container(txc_hash_table_t *tx_stats,
00192                            txc_stats_txstat_t *txstat, 
00193                            txc_stats_txstat_t **txstat_containerp)
00194 {
00195         txc_hash_table_key_t   key;
00196         txc_hash_table_value_t value;
00197         txc_stats_txstat_t     *txstat_container;
00198 
00199         /* 
00200          * Find the txstat container of the static transaction, and if there is
00201          * no such container create it and insert it into the hash table.
00202          */
00203         key = (txc_hash_table_key_t) txstat->srcloc_str;
00204         if (txc_hash_table_lookup(tx_stats, key, &value) 
00205             == TXC_R_SUCCESS)
00206         {
00207                 txstat_container = (txc_stats_txstat_t *) value;        
00208         } else {
00209                 txstat_container = (txc_stats_txstat_t *) MALLOC(sizeof(txc_stats_txstat_t));
00210                 stats_txstat_reset(txstat_container);
00211                 txstat_container->count = 0;
00212                 txstat_container->srcloc_str = txstat->srcloc_str;
00213                 txstat_container->srcloc.line = txstat->srcloc.line;
00214                 txstat_container->srcloc.fun = txstat->srcloc.fun;
00215                 txstat_container->srcloc.file = txstat->srcloc.file;
00216                 txc_hash_table_add(tx_stats, 
00217                                    key, 
00218                                    (txc_hash_table_value_t) (txstat_container));
00219         }
00220 
00221         *txstat_containerp = txstat_container;
00222 }
00223 
00224 
00225 static
00226 void 
00227 statsmgr_commit_action(void *args, int *result)
00228 {
00229         txc_tx_t               *txd = (txc_tx_t *) args;
00230         txc_stats_txstat_t     *txstat = txd->txstat;
00231         txc_stats_txstat_t     *txstat_all;
00232         txc_stats_threadstat_t *threadstat = txd->threadstat;
00233         int                    i;
00234 
00235 
00236         /* 
00237          * Find the txstat container of the static transaction, and if there is
00238          * no such container create it and insert it into the hash table.
00239          */
00240         stats_get_txstat_container(threadstat->tx_stats, txstat, &txstat_all);
00241 
00242         /* 
00243          * Collect the statistics of this transaction instance into its static 
00244          * container. 
00245          */
00246         txstat_all->count++;
00247         for (i=0; i<txc_stats_numofstats; i++) {
00248                 txstat_all->total_stats[i].total += txstat->total_stats[i].total;
00249                 txstat_all->total_stats[i].min = MIN(txstat_all->total_stats[i].min,
00250                                                      txstat->total_stats[i].total);
00251                 txstat_all->total_stats[i].max = MAX(txstat_all->total_stats[i].max,
00252                                                      txstat->total_stats[i].total);
00253         }
00254 
00255         /* 
00256          * Collect the statistics of this transaction instance into the thread's 
00257          * statistics container. 
00258          */
00259         threadstat->count++;
00260         for (i=0; i<txc_stats_numofstats; i++) {
00261                 threadstat->total_stats[i].total += txstat->total_stats[i].total;
00262                 threadstat->total_stats[i].min = MIN(threadstat->total_stats[i].min,
00263                                                      txstat->total_stats[i].total);
00264                 threadstat->total_stats[i].max = MAX(threadstat->total_stats[i].max,
00265                                                      txstat->total_stats[i].total);
00266         }
00267         if (result) {
00268                 *result = 0;
00269         }
00270 }
00271 
00272 
00273 static 
00274 void 
00275 statsmgr_undo_action(void *args, int *result)
00276 {
00277         txc_tx_t *txd = (txc_tx_t *) args;
00278 
00279         /* reset transaction statistics */
00280 
00281         stats_txstat_reset(txd->txstat);
00282 
00283         if (result) {
00284                 *result = 0;
00285         }
00286 }
00287 
00288 
00289 static inline
00290 void
00291 register_statsmgr_commit_action(txc_tx_t *txd)
00292 {
00293         if (txd->statsmgr_commit_action_registered == 0) {
00294                 txc_tx_register_commit_action(txd, 
00295                                               statsmgr_commit_action, 
00296                                               (void *) txd,
00297                                               NULL,
00298                                           TXC_STATSMGR_COMMIT_ACTION_ORDER);
00299                 txd->statsmgr_commit_action_registered = 1;                                                       
00300         }
00301 }
00302 
00303 
00304 static inline
00305 void
00306 register_statsmgr_undo_action(txc_tx_t *txd)
00307 {
00308         if (txd->statsmgr_undo_action_registered == 0) {
00309                 txc_tx_register_undo_action(txd, 
00310                                         statsmgr_undo_action,
00311                                             (void *) txd,
00312                                              NULL,
00313                                          TXC_STATSMGR_UNDO_ACTION_ORDER);
00314                 txd->statsmgr_undo_action_registered = 1;                                                         
00315         }
00316 }
00317 
00318 
00319 void
00320 txc_stats_register_statsmgr_commit_action(txc_tx_t *txd)
00321 {
00322         register_statsmgr_commit_action(txd);
00323 }
00324 
00325 
00326 void
00327 txc_stats_register_statsmgr_undo_action(txc_tx_t *txd)
00328 {
00329         register_statsmgr_undo_action(txd);
00330 }
00331 
00332 
00333 void
00334 txc_stats_transaction_postbegin(txc_tx_t *txd)
00335 {
00336         if (txc_runtime_settings.statistics == TXC_BOOL_TRUE)
00337     {
00338                 register_statsmgr_commit_action(txd);
00339                 register_statsmgr_undo_action(txd);
00340         }       
00341 }
00342 
00343 
00344 static
00345 void
00346 stats_txstat_print(FILE *fout, 
00347                    txc_stats_txstat_t *txstat, 
00348                                    int shiftlen,
00349                    txc_bool_t print_srcloc)
00350 {
00351         int                     i;
00352         char                    header[512];
00353         double                  mean;
00354         txc_stats_statcounter_t max;
00355         txc_stats_statcounter_t min;
00356         txc_stats_statcounter_t total;
00357         txc_stats_statcounter_t count;
00358 
00359         if (print_srcloc) {
00360                 sprintf(header, "Source is line %d in function %s in %s", 
00361                         txstat->srcloc.line, 
00362                                 txstat->srcloc.fun,
00363                     txstat->srcloc.file);
00364                 fprintf(fout, "%s%s\n\n", WHITESPACE(shiftlen), header);
00365         }
00366 
00367         fprintf(fout, "%s%s%s:%13s%13s%13s%13s\n", 
00368                 WHITESPACE(shiftlen+2),
00369                 "",
00370                         WHITESPACE(25),
00371                         "Min",
00372                         "Mean",
00373                         "Max",
00374                         "Total");
00375 
00376         count = txstat->count;
00377 
00378         fprintf(fout, "%s%s%s:%13s%13s%13s%13u\n", 
00379                 WHITESPACE(shiftlen+2),
00380                 "Transactions",
00381                         WHITESPACE(25 - strlen("Transactions")),
00382                         "",
00383                         "",
00384                         "",
00385                         count);
00386         
00387         for (i=0; i<txc_stats_numofstats; i++) {
00388                 total = txstat->total_stats[i].total;
00389                 min = txstat->total_stats[i].min;
00390                 max = txstat->total_stats[i].max;
00391                 mean = (double) total / (double) count;
00392                 fprintf(fout, "%s%s%s:%13u%13.2f%13u%13u\n", 
00393                         WHITESPACE(shiftlen+2),
00394                         stats_strings[i],
00395                                 WHITESPACE(25 - strlen(stats_strings[i])),
00396                                 min,
00397                                 mean,
00398                                 max,
00399                                 total);
00400         }
00401 }
00402 
00403 
00404 static
00405 void
00406 stats_threadstat_print(FILE *fout, 
00407                        txc_stats_threadstat_t *threadstat) 
00408 {
00409         txc_hash_table_iter_t  iter;
00410         txc_hash_table_key_t   key;
00411         txc_hash_table_value_t value;
00412         txc_stats_txstat_t     *txstat;
00413         txc_stats_txstat_t     txstat_all;
00414         int                    i;
00415 
00416         txstat_all.count = threadstat->count;
00417         for (i=0; i<txc_stats_numofstats; i++) {
00418                 txstat_all.total_stats[i] = threadstat->total_stats[i];
00419         }       
00420         fprintf(fout, "Thread %u\n", threadstat->txd->tid);
00421         stats_txstat_print(fout, &txstat_all, 0, TXC_BOOL_FALSE);
00422         fprintf(fout, "\n");
00423         fprintf(fout, "  Transactions for thread %u\n\n", threadstat->txd->tid);
00424         
00425         txc_hash_table_iter_init(threadstat->tx_stats, &iter);
00426         while(TXC_R_SUCCESS == txc_hash_table_iter_next(&iter, &key, &value)) {
00427                 txstat = (txc_stats_txstat_t *) value;
00428                 stats_txstat_print(fout, txstat, 4, TXC_BOOL_TRUE);
00429                 fprintf(fout, "\n");
00430         }
00431 }
00432 
00433 
00434 static
00435 void
00436 stats_summarize_all(txc_statsmgr_t *statsmgr, txc_stats_threadstat_t *summary)
00437 {
00438         txc_stats_threadstat_t *threadstat;
00439         txc_hash_table_iter_t  iter;
00440         txc_stats_txstat_t     *txstat;
00441         txc_stats_txstat_t     *txstat_summary;
00442         txc_hash_table_key_t   key;
00443         txc_hash_table_value_t value;
00444         int                    i;
00445 
00446         for (threadstat=statsmgr->alloc_threadstat_list_head;
00447              threadstat;
00448                  threadstat = threadstat->next)
00449         {
00450                 txc_hash_table_iter_init(threadstat->tx_stats, &iter);
00451                 while(TXC_R_SUCCESS == txc_hash_table_iter_next(&iter, &key, &value)) {
00452                         txstat = (txc_stats_txstat_t *) value;
00453                         stats_get_txstat_container(summary->tx_stats, txstat, &txstat_summary);
00454                         txstat_summary->count += txstat->count;
00455                         summary->count += txstat->count;
00456                         for (i=0; i<txc_stats_numofstats; i++) {
00457                                 txstat_summary->total_stats[i].total += txstat->total_stats[i].total;
00458                                 txstat_summary->total_stats[i].min = MIN(txstat_summary->total_stats[i].min,
00459                                                                          txstat->total_stats[i].min);
00460                                 txstat_summary->total_stats[i].max = MAX(txstat_summary->total_stats[i].max,
00461                                                                          txstat->total_stats[i].max);
00462 
00463                                 summary->total_stats[i].total += txstat->total_stats[i].total;
00464                                 summary->total_stats[i].min = MIN(summary->total_stats[i].min,
00465                                                                   txstat->total_stats[i].min);
00466                                 summary->total_stats[i].max = MAX(summary->total_stats[i].max,
00467                                                                   txstat->total_stats[i].max);
00468                         }
00469                 }
00470         }       
00471 }
00472 
00473 
00485 void
00486 txc_stats_print(txc_statsmgr_t *statsmgr)
00487 {
00488         txc_hash_table_iter_t  iter;
00489         txc_stats_threadstat_t *threadstat;
00490         txc_stats_threadstat_t summary;
00491         txc_hash_table_key_t   key;
00492         txc_hash_table_value_t value;
00493         txc_stats_txstat_t     *txstat;
00494         txc_stats_txstat_t     txstat_grand_total;
00495         int                    i;
00496         FILE                   *fout;
00497 
00498         if (txc_runtime_settings.statistics == TXC_BOOL_FALSE) {
00499                 return;
00500         }
00501 
00502         fout = fopen(txc_runtime_settings.statistics_file, "w");
00503 
00504         /* Print per THREAD per TRANSACTION totals */
00505         fprintf(fout, "STATS REPORT\n");
00506         fprintf(fout, "THREAD TOTALS\n\n");
00507 
00508         for (threadstat=statsmgr->alloc_threadstat_list_head;
00509              threadstat;
00510                  threadstat = threadstat->next)
00511         {       
00512                 stats_threadstat_print(fout, threadstat);
00513                 fprintf(fout, "\n");
00514         }
00515 
00516 
00517         /* Print per TRANSACTION totals */
00518         fprintf(fout, "TRANSACTION TOTALS\n\n");
00519         txc_hash_table_create(&(summary.tx_stats),
00520                               TXC_STATS_THREADSTAT_HASHTABLE_SIZE, 
00521                                                   TXC_BOOL_FALSE);
00522         for (i=0; i<txc_stats_numofstats; i++) {
00523                 summary.total_stats[i].min = 0;
00524                 summary.total_stats[i].max = 0;
00525                 summary.total_stats[i].total = 0;
00526                 summary.count = 0;
00527         }       
00528         stats_summarize_all(statsmgr, &summary);
00529         txc_hash_table_iter_init(summary.tx_stats, &iter);
00530         while(TXC_R_SUCCESS == txc_hash_table_iter_next(&iter, &key, &value)) {
00531                 txstat = (txc_stats_txstat_t *) value;
00532                 stats_txstat_print(fout, txstat, 0, TXC_BOOL_TRUE);
00533                 fprintf(fout, "\n");
00534         }
00535 
00536         /* Print GRAND totals */
00537         fprintf(fout, "GRAND TOTAL (all transactions, all threads)\n\n");
00538         txstat_grand_total.count = summary.count;
00539         for (i=0; i<txc_stats_numofstats; i++) {
00540                 txstat_grand_total.total_stats[i] = summary.total_stats[i];
00541         }       
00542         stats_txstat_print(fout, &txstat_grand_total, 0, TXC_BOOL_FALSE);
00543         
00544         fclose(fout);
00545 }       

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7