1/*---------------------------------------------------------------------------* 2 * comp_stats.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 21 22#include "buildopt.h" 23#include "pstdio.h" 24#include "passert.h" 25#include <time.h> 26#include "comp_stats.h" 27#include "portable.h" 28#include "PFile.h" 29 30#ifdef SET_RCSID 31static const char *rcsid = 0 ? (const char *) &rcsid : "$Id: compstats now"; 32#endif 33 34#if defined(__cplusplus) 35extern "C" 36{ 37#endif 38 COMP_STATS *comp_stats = NULL; 39#if defined(__cplusplus) 40} 41#endif 42 43/* create COMP_STATS object */ 44 45COMP_STATS *init_comp_stats(void) 46{ 47 static COMP_STATS c; 48 49 /*c = (COMP_STATS *) calloc( 1, sizeof( COMP_STATS ));*/ 50 /*c = (COMP_STATS *) NEW( COMP_STATS, L("crec.comp_stats")); */ 51 52 init_cs_clock(&c.overall_search); 53 init_cs_clock(&c.models); 54 init_cs_clock(&c.fsm_to_hmm); 55 init_cs_clock(&c.internal_hmm); 56 init_cs_clock(&c.hmm_to_fsm); 57 init_cs_clock(&c.epsilon); 58 init_cs_clock(&c.astar); 59 init_cs_clock(&c.prune); 60 init_cs_clock(&c.front_end); 61 init_cs_clock(&c.word_lookup); 62 init_cs_clock(&c.word_addition); 63 c.total_time = 0; 64 return &c; 65} 66 67 68void dump_comp_stats(COMP_STATS *cs, PFile* fp) 69{ 70 if (getenv("HIDE_COMP_STATS")) 71 return; 72#if !defined(_WIN32) && !defined(__vxworks) 73 if (clock() == (clock_t) - 1) 74 { 75 pfprintf(fp, "***WARNING: clock overrun!\n"); 76 } 77#endif 78 if (!cs) cs = comp_stats; 79 80#ifdef SREC_ENGINE_VERBOSE_LOGGING 81 pfprintf(fp, "Total Time %5.2f Seconds\n", cs->total_time); 82#endif 83 print_cs_clock(&cs->front_end, cs->total_time, fp, "Front end", "Frames"); 84 print_cs_clock(&cs->overall_search, cs->total_time, fp, "Total Search", "Frames"); 85 print_cs_clock(&cs->models, cs->total_time, fp, " Models", "Models"); 86 print_cs_clock(&cs->internal_hmm, cs->total_time, fp, " Internal HMM", "HMMs"); 87 print_cs_clock(&cs->fsm_to_hmm, cs->total_time, fp, " FSM to HMM", "FSM_Nodes"); 88 print_cs_clock(&cs->prune, cs->total_time, fp, " Prune", "HMM States"); 89 print_cs_clock(&cs->hmm_to_fsm, cs->total_time, fp, " HMM to FSM", "HMMS"); 90 print_cs_clock(&cs->epsilon, cs->total_time, fp, " Epsilon", "FSM_Nodes"); 91 print_cs_clock(&cs->astar, cs->total_time, fp, " Astar", "Utterances"); 92 print_cs_clock(&cs->word_lookup, cs->total_time, fp, " WordLookup", "Words"); 93 print_cs_clock(&cs->word_addition, cs->total_time, fp, " WordAdd'tn", "Pronunciations"); 94 pfflush(fp); 95} 96 97 98void print_cs_clock(CS_CLOCK *c, float num_seconds, PFile* fp, char *prompt, char *item_name) 99{ 100 if (c == NULL) return; 101 /* FPRINTF( fp, "%15.15s %8.2f. Per Second of speech: %6.2f ms, %6.2f calls, %6.2f (%d) %s\n", 102 prompt ? prompt : "", 103 c->total_time/c->clocks_per_msec, 104 (c->total_time/c->clocks_per_msec) / num_seconds, 105 c->ncalls / num_seconds, 106 c->item_count / num_seconds, 107 c->item_count, 108 item_name);*/ 109} 110 111 112void start_cs_clock(CS_CLOCK *c) 113{ 114 if (c == NULL) return; 115#ifdef _WIN32 116 { 117 FILETIME dummy, kernelCPU, userCPU; 118 GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernelCPU, 119 &userCPU); 120 c->last = kernelCPU.dwLowDateTime + ((__int64)kernelCPU.dwHighDateTime << 32) + 121 userCPU.dwLowDateTime + ((__int64)userCPU.dwHighDateTime << 32); 122 } 123#elif defined(__vxworks) 124 /* Should use a portable clock() */ 125 /* WxWorks: clock() always returns -1. VxWorks does not track per-task time or system idle time. 126 There is no method of determining how long a task or the entire system has been doing work. 127 tickGet( ) can be used to query the number of system ticks since system start. 128 clock_gettime( ) can be used to get the current clock time. 129 */ 130 c->last = tickGet(); 131#else 132 c->last = clock(); 133#endif 134} 135 136 137 138void end_cs_clock(CS_CLOCK *c, int count) 139{ 140 CS_TIME curr; 141 if (c == NULL) return; 142#ifdef _WIN32 143 { 144 FILETIME dummy, kernelCPU, userCPU; 145 GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernelCPU, 146 &userCPU); 147 curr = kernelCPU.dwLowDateTime + ((__int64)kernelCPU.dwHighDateTime << 32) + 148 userCPU.dwLowDateTime + ((__int64)userCPU.dwHighDateTime << 32); 149 } 150#elif defined(__vxworks) 151 curr = tickGet(); 152#else 153 curr = clock(); 154 if (curr == -1) return; /* clock overrun */ 155#endif 156 c->total_time += curr - c->last; 157 c->last = curr; 158 c->ncalls ++; 159 c->item_count += count; 160} 161 162 163void reset_cs_clock(CS_CLOCK *c) 164{ 165 if (c == NULL) return; 166 c->ncalls = 0; 167 c->total_time = 0; 168 c->last = 0; 169 c->item_count = 0; 170} 171 172void init_cs_clock(CS_CLOCK *c) 173{ 174 if (c == NULL) return; 175#if _WIN32 176 c->clocks_per_msec = 10000.0; 177#else 178 c->clocks_per_msec = (double) CLOCKS_PER_SEC / 1000.0; 179#endif 180 reset_cs_clock(c); 181} 182 183 184CS_CLOCK *make_cs_clock(void) 185{ 186 CS_CLOCK *c = (CS_CLOCK *) NEW(CS_CLOCK, L("crec.cs_clock")); 187 init_cs_clock(c); 188 return c; 189} 190