usermode/library/mtm/src/stats.c

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2011 Computer Sciences Department, 
00003     University of Wisconsin -- Madison
00004 
00005     ----------------------------------------------------------------------
00006 
00007     This file is part of Mnemosyne: Lightweight Persistent Memory, 
00008     originally developed at the University of Wisconsin -- Madison.
00009 
00010     Mnemosyne was originally developed primarily by Haris Volos
00011     with contributions from Andres Jaan Tack.
00012 
00013     ----------------------------------------------------------------------
00014 
00015     Mnemosyne is free software; you can redistribute it and/or
00016     modify it under the terms of the GNU General Public License
00017     as published by the Free Software Foundation, version 2
00018     of the License.
00019  
00020     Mnemosyne is distributed in the hope that it will be useful,
00021     but WITHOUT ANY WARRANTY; without even the implied warranty of
00022     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023     GNU General Public License for more details.
00024 
00025     You should have received a copy of the GNU General Public License
00026     along with this program; if not, write to the Free Software
00027     Foundation, Inc., 51 Franklin Street, Fifth Floor, 
00028     Boston, MA  02110-1301, USA.
00029 
00030 ### END HEADER ###
00031 */
00032 
00040 #include <stdbool.h>
00041 #include <string.h>
00042 #include "stats.h"
00043 #include "chhash.h"
00044 #include "util.h"
00045 #include "debug.h"
00046 
00047 m_statsmgr_t *m_g_statsmgr;
00048 
00049 #define M_STATS_THREADSTAT_HASHTABLE_SIZE 128
00050 
00051 #define MIN(A, B) (((A) < (B)) ? (A) : (B))
00052 #define MAX(A, B) (((A) > (B)) ? (A) : (B))
00053 
00054 #define ACTION(name) #name,
00055 char *stats_strings[] = {
00056         FOREACH_STAT(ACTION)
00057 };      
00058 #undef ACTION   
00059 
00060 static const char __whitespaces[] = "                                                              ";
00061 
00062 #define WHITESPACE(len) &__whitespaces[sizeof(__whitespaces) - (len) -1]
00063 
00065 struct m_stats_threadstat_s {
00066     unsigned int tid;
00067         m_stats_statset_t           summary_statset; 
00068         m_chhash_t                  *stats_table; 
00069         struct m_stats_threadstat_s *next;     
00070         struct m_stats_threadstat_s *prev;     
00071 };
00072 
00073 
00075 struct m_statsmgr_s {
00076         m_mutex_t            mutex;                       
00077         char                 *output_file;
00078         unsigned int         alloc_threadstat_num;        
00079         m_stats_threadstat_t *alloc_threadstat_list_head; 
00080         m_stats_threadstat_t *alloc_threadstat_list_tail; 
00081 };
00082 
00083 
00084 m_result_t
00085 m_statsmgr_create(m_statsmgr_t **statsmgrp, char *output_file)
00086 {
00087         *statsmgrp = (m_statsmgr_t *) MALLOC(sizeof(m_statsmgr_t));
00088         if (*statsmgrp == NULL) {
00089                 return M_R_NOMEMORY;
00090         }
00091         (*statsmgrp)->output_file = output_file;
00092         (*statsmgrp)->alloc_threadstat_num = 0;
00093         (*statsmgrp)->alloc_threadstat_list_head = (*statsmgrp)->alloc_threadstat_list_tail = NULL;
00094         M_MUTEX_INIT(&(*statsmgrp)->mutex, NULL);
00095 
00096         return M_R_SUCCESS;
00097 }
00098 
00099 
00100 m_result_t
00101 m_statsmgr_destroy(m_statsmgr_t **statsmgrp)
00102 {
00103         m_stats_threadstat_t *threadstat;
00104         m_stats_threadstat_t *threadstat_next;
00105         m_statsmgr_t         *statsmgr = *statsmgrp;
00106 
00107 
00108         for (threadstat=statsmgr->alloc_threadstat_list_head;
00109              threadstat != NULL;
00110                  threadstat = threadstat_next)
00111         {
00112                 threadstat_next = threadstat->next;
00113                 FREE(threadstat);
00114         }
00115 
00116         FREE(statsmgr);
00117         *statsmgrp = NULL;
00118 
00119         return M_R_SUCCESS;
00120 }
00121 
00122 
00123 m_result_t
00124 m_stats_threadstat_create(m_statsmgr_t *statsmgr, 
00125                           unsigned int tid, 
00126                           m_stats_threadstat_t **threadstatp)
00127 {
00128         m_stats_threadstat_t *threadstat;
00129         int                  i;
00130 
00131         threadstat = (m_stats_threadstat_t *) MALLOC(sizeof(m_stats_threadstat_t));
00132 
00133         M_MUTEX_LOCK(&(statsmgr->mutex));
00134         if (statsmgr->alloc_threadstat_list_head == NULL) {
00135                 M_ASSERT(statsmgr->alloc_threadstat_list_tail == NULL);
00136                 statsmgr->alloc_threadstat_list_head = threadstat;
00137                 statsmgr->alloc_threadstat_list_tail = threadstat;
00138                 threadstat->next = NULL;
00139                 threadstat->prev = NULL;
00140         } else {
00141                 statsmgr->alloc_threadstat_list_tail->next = threadstat;
00142                 threadstat->prev = statsmgr->alloc_threadstat_list_tail;
00143                 statsmgr->alloc_threadstat_list_tail = threadstat;
00144         }
00145         statsmgr->alloc_threadstat_num++;
00146         M_MUTEX_UNLOCK(&(statsmgr->mutex));
00147 
00148         m_stats_statset_init(&(threadstat->summary_statset), NULL);
00149         threadstat->tid = tid;
00150         m_chhash_create(&threadstat->stats_table, 
00151                         M_STATS_THREADSTAT_HASHTABLE_SIZE, 
00152                                         false);
00153         *threadstatp = threadstat;
00154         return M_R_SUCCESS;                                       
00155 }
00156 
00157 
00158 m_result_t
00159 m_stats_statset_create(m_stats_statset_t **statsetp)
00160 {
00161         m_stats_statset_t *statset;
00162 
00163         statset = (m_stats_statset_t *) MALLOC(sizeof(m_stats_statset_t));
00164         statset->count = 0;
00165         *statsetp = statset;
00166 
00167         return M_R_SUCCESS;                                       
00168 }
00169 
00170 
00171 m_result_t
00172 m_stats_statset_destroy(m_stats_statset_t **statsetp)
00173 {
00174         FREE(*statsetp);
00175         *statsetp = NULL;
00176 
00177         return M_R_SUCCESS;                                       
00178 }
00179 
00180 
00181 static
00182 void
00183 stats_statset_reset(m_stats_statset_t *statset)
00184 {
00185 #define RESETSTAT(name)                                                      \
00186   statset->stats[m_stats_##name##_stat].total = 0;                    \
00187   statset->stats[m_stats_##name##_stat].min = 0xFFFFFFFF;             \
00188   statset->stats[m_stats_##name##_stat].max = 0;
00189 
00190         FOREACH_STAT (RESETSTAT)
00191 
00192 #undef RESETSTAT        
00193 }
00194 
00195 
00196 m_result_t
00197 m_stats_statset_init(m_stats_statset_t *statset, 
00198                      const char *name)
00199 {
00200         statset->count = 0;
00201         statset->name = name;
00202         stats_statset_reset(statset);
00203         return M_R_SUCCESS;
00204 }
00205 
00206 
00207 static
00208 m_result_t
00209 stats_get_statset(m_chhash_t *stats_table,
00210                   const char *name, 
00211                   m_stats_statset_t **statsetp)
00212 {
00213         m_chhash_key_t    key;
00214         m_chhash_value_t  value;
00215         m_stats_statset_t *statset;
00216         key = (m_chhash_key_t) name;
00217         if (m_chhash_lookup(stats_table, key, &value) == M_R_SUCCESS)
00218         {
00219                 statset = (m_stats_statset_t *) value;  
00220                 *statsetp = statset;
00221                 return M_R_SUCCESS;
00222         }
00223         return M_R_FAILURE;
00224 }
00225 
00226 
00227 /* 
00228  * Collect the statistics of source_statset into dest_statset.
00229  */
00230 void 
00231 stats_aggregate(m_stats_statset_t *dest_statset, 
00232                 m_stats_statset_t *source_statset)
00233 {
00234         int i;
00235 
00236         dest_statset->count++;
00237         for (i=0; i<m_stats_numofstats; i++) {
00238                 dest_statset->stats[i].total += source_statset->stats[i].total;
00239                 dest_statset->stats[i].min = MIN(dest_statset->stats[i].min,
00240                                                  source_statset->stats[i].total);
00241                 dest_statset->stats[i].max = MAX(dest_statset->stats[i].max,
00242                                                  source_statset->stats[i].total);
00243         }
00244 }
00245 
00246 
00247 void 
00248 m_stats_threadstat_aggregate(m_stats_threadstat_t *threadstat, m_stats_statset_t *source_statset)
00249 {
00250         m_stats_statset_t    *statset_all;
00251         m_result_t           result;
00252 
00253 
00254         result = stats_get_statset(threadstat->stats_table, source_statset->name, &statset_all);
00255         if (result != M_R_SUCCESS) {
00256                 m_stats_statset_create(&statset_all);
00257                 m_stats_statset_init(statset_all, source_statset->name);
00258                 m_chhash_add(threadstat->stats_table, 
00259                              (m_chhash_key_t) source_statset->name, 
00260                              (m_chhash_value_t) (statset_all));
00261         }
00262 
00263         
00264         stats_aggregate(statset_all, source_statset);
00265         stats_aggregate(&threadstat->summary_statset, source_statset);
00266 }
00267 
00268 
00269 
00270 static
00271 void
00272 m_stats_statset_print(FILE *fout, 
00273                       m_stats_statset_t *statset, 
00274                       int shiftlen,
00275                       int print_header)
00276 {
00277         int                     i;
00278         char                    header[512];
00279         double                  mean;
00280         m_stats_statcounter_t max;
00281         m_stats_statcounter_t min;
00282         m_stats_statcounter_t total;
00283         m_stats_statcounter_t count;
00284 
00285         if (print_header) {
00286                 sprintf(header, "Transaction: %s", statset->name);
00287                 fprintf(fout, "%s%s\n\n", WHITESPACE(shiftlen), header);
00288         }
00289 
00290         fprintf(fout, "%s%s%s:%13s%13s%13s%13s\n", 
00291                 WHITESPACE(shiftlen+2),
00292                 "",
00293                         WHITESPACE(25),
00294                         "Min",
00295                         "Mean",
00296                         "Max",
00297                         "Total");
00298 
00299         count = statset->count;
00300 
00301         fprintf(fout, "%s%s%s:%13s%13s%13s%13u\n", 
00302                 WHITESPACE(shiftlen+2),
00303                 "Transactions",
00304                         WHITESPACE(25 - strlen("Transactions")),
00305                         "",
00306                         "",
00307                         "",
00308                         count);
00309         
00310         for (i=0; i<m_stats_numofstats; i++) {
00311                 total = statset->stats[i].total;
00312                 min = statset->stats[i].min;
00313                 max = statset->stats[i].max;
00314                 mean = (double) total / (double) count;
00315                 fprintf(fout, "%s%s%s:%13u%13.2f%13u%13u\n", 
00316                         WHITESPACE(shiftlen+2),
00317                         stats_strings[i],
00318                                 WHITESPACE(25 - strlen(stats_strings[i])),
00319                                 min,
00320                                 mean,
00321                                 max,
00322                                 total);
00323         }
00324 }
00325 
00326 
00327 static
00328 void
00329 stats_threadstat_print(FILE *fout, 
00330                        m_stats_threadstat_t *threadstat) 
00331 {
00332         m_chhash_iter_t   iter;
00333         m_chhash_key_t    key;
00334         m_chhash_value_t  value;
00335         m_stats_statset_t *statset;
00336         m_stats_statset_t statset_all;
00337         int               i;
00338 
00339         fprintf(fout, "Thread %u\n", threadstat->tid);
00340         m_stats_statset_print(fout, &threadstat->summary_statset, 0, false);
00341         fprintf(fout, "\n");
00342         fprintf(fout, "  Transactions for thread %u\n\n", threadstat->tid);
00343         
00344         m_chhash_iter_init(threadstat->stats_table, &iter);
00345         while(M_R_SUCCESS == m_chhash_iter_next(&iter, &key, &value)) {
00346                 statset = (m_stats_statset_t *) value;
00347                 m_stats_statset_print(fout, statset, 4, true);
00348                 fprintf(fout, "\n");
00349         }
00350 }
00351 
00352 
00353 static
00354 void
00355 stats_summarize_all(m_statsmgr_t *statsmgr, m_stats_threadstat_t *summary)
00356 {
00357         m_stats_threadstat_t *threadstat;
00358         m_chhash_iter_t      iter;
00359         m_stats_statset_t    *statset;
00360         m_stats_statset_t    *statset_summary;
00361         m_chhash_key_t       key;
00362         m_chhash_value_t     value;
00363         int                  i;
00364         m_result_t           result;
00365 
00366 
00367         for (threadstat=statsmgr->alloc_threadstat_list_head;
00368              threadstat;
00369                  threadstat = threadstat->next)
00370         {
00371                 m_chhash_iter_init(threadstat->stats_table, &iter);
00372                 while(M_R_SUCCESS == m_chhash_iter_next(&iter, &key, &value)) {
00373                         statset = (m_stats_statset_t *) value;
00374                         result = stats_get_statset(summary->stats_table, 
00375                                                    statset->name, &statset_summary);
00376                         if (result != M_R_SUCCESS) {
00377                                 m_stats_statset_create(&statset_summary);
00378                                 m_stats_statset_init(statset_summary, statset->name);
00379                                 m_chhash_add(summary->stats_table, 
00380                                          (m_chhash_key_t) statset->name, 
00381                                          (m_chhash_value_t) (statset_summary));
00382                         }
00383                         statset_summary->count += statset->count;
00384                         summary->summary_statset.count += statset->count;
00385                         for (i=0; i<m_stats_numofstats; i++) {
00386                                 statset_summary->stats[i].total += statset->stats[i].total;
00387                                 statset_summary->stats[i].min = MIN(statset_summary->stats[i].min,
00388                                                                          statset->stats[i].min);
00389                                 statset_summary->stats[i].max = MAX(statset_summary->stats[i].max,
00390                                                                          statset->stats[i].max);
00391 
00392                                 summary->summary_statset.stats[i].total += statset->stats[i].total;
00393                                 summary->summary_statset.stats[i].min = MIN(summary->summary_statset.stats[i].min,
00394                                                                             statset->stats[i].min);
00395                                 summary->summary_statset.stats[i].max = MAX(summary->summary_statset.stats[i].max,
00396                                                                             statset->stats[i].max);
00397                         }
00398                 }
00399         }       
00400 }
00401 
00402 
00414 void
00415 m_stats_print(m_statsmgr_t *statsmgr)
00416 {
00417         m_chhash_iter_t      iter;
00418         m_stats_threadstat_t *threadstat;
00419         m_stats_threadstat_t summary;
00420         m_chhash_key_t       key;
00421         m_chhash_value_t     value;
00422         m_stats_statset_t    *statset;
00423         m_stats_statset_t    statset_grand_total;
00424         int                  i;
00425         FILE                 *fout;
00426 
00427         if (statsmgr->output_file) {
00428                 printf("OUTPUT STATS >> %s\n", statsmgr->output_file);
00429                 fout = fopen(statsmgr->output_file, "w");
00430         } else {        
00431                 fout = stderr;
00432         }
00433 
00434         /* Print per THREAD per TRANSACTION totals */
00435         fprintf(fout, "STATS REPORT\n");
00436         fprintf(fout, "THREAD TOTALS\n\n");
00437 
00438         for (threadstat=statsmgr->alloc_threadstat_list_head;
00439              threadstat;
00440                  threadstat = threadstat->next)
00441         {       
00442                 stats_threadstat_print(fout, threadstat);
00443                 fprintf(fout, "\n");
00444         }
00445 
00446         /* Print per TRANSACTION totals */
00447         fprintf(fout, "TRANSACTION TOTALS\n\n");
00448         m_chhash_create(&(summary.stats_table),
00449                         M_STATS_THREADSTAT_HASHTABLE_SIZE, 
00450                     false);
00451         m_stats_statset_init(&summary.summary_statset, NULL);                                     
00452         stats_summarize_all(statsmgr, &summary);
00453         m_chhash_iter_init(summary.stats_table, &iter);
00454         while(M_R_SUCCESS == m_chhash_iter_next(&iter, &key, &value)) {
00455                 statset = (m_stats_statset_t *) value;
00456                 m_stats_statset_print(fout, statset, 0, true);
00457                 fprintf(fout, "\n");
00458         }
00459 
00460         /* Print GRAND totals */
00461         fprintf(fout, "GRAND TOTAL (all transactions, all threads)\n\n");
00462         statset_grand_total.count = summary.summary_statset.count;
00463         for (i=0; i<m_stats_numofstats; i++) {
00464                 statset_grand_total.stats[i] = summary.summary_statset.stats[i];
00465         }       
00466         m_stats_statset_print(fout, &statset_grand_total, 0, false);
00467         if (statsmgr->output_file) {
00468                 fclose(fout);
00469         }       
00470 }       

Generated on Sat Apr 23 11:43:36 2011 for Mnemosyne by  doxygen 1.4.7