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