| rev |
line source |
|
Me@50
|
1 /*
|
|
Me@50
|
2 * Copyright 2010 OpenSourceStewardshipFoundation
|
|
Me@50
|
3 *
|
|
Me@50
|
4 * Licensed under BSD
|
|
Me@50
|
5 */
|
|
Me@50
|
6
|
|
Me@50
|
7 #include <stdio.h>
|
|
Me@50
|
8 #include <stdlib.h>
|
|
Me@50
|
9 #include <malloc.h>
|
|
Me@50
|
10 #include <sys/time.h>
|
|
Me@52
|
11 #include <string.h>
|
|
Me@50
|
12
|
|
Me@50
|
13 #include "VMS.h"
|
|
Me@50
|
14 #include "Queue_impl/BlockingQueue.h"
|
|
Me@50
|
15 #include "Histogram/Histogram.h"
|
|
Me@50
|
16
|
|
Me@50
|
17
|
|
Me@50
|
18 //================================ STATS ====================================
|
|
Me@50
|
19
|
|
Me@50
|
20 inline TSCount getTSCount()
|
|
Me@50
|
21 { unsigned int low, high;
|
|
Me@50
|
22 TSCount out;
|
|
Me@50
|
23
|
|
Me@50
|
24 saveTimeStampCountInto( low, high );
|
|
Me@50
|
25 out = high;
|
|
Me@50
|
26 out = (out << 32) + low;
|
|
Me@50
|
27 return out;
|
|
Me@50
|
28 }
|
|
Me@50
|
29
|
|
Me@50
|
30
|
|
Me@50
|
31
|
|
Me@50
|
32 //==================== Probes =================
|
|
Me@50
|
33 #ifdef STATS__USE_TSC_PROBES
|
|
Me@50
|
34
|
|
Me@50
|
35 int32
|
|
Me@50
|
36 VMS__create_histogram_probe( int32 numBins, float32 startValue,
|
|
Me@50
|
37 float32 binWidth, char *nameStr )
|
|
Me@50
|
38 { IntervalProbe *newProbe;
|
|
Me@50
|
39 int32 idx;
|
|
Me@50
|
40 FloatHist *hist;
|
|
Me@50
|
41
|
|
Me@50
|
42 idx = VMS__create_single_interval_probe( nameStr );
|
|
Me@50
|
43 newProbe = _VMSMasterEnv->intervalProbes[ idx ];
|
|
Me@50
|
44
|
|
Me@50
|
45 hist = makeFloatHistogram( numBins, startValue, binWidth );
|
|
Me@50
|
46 newProbe->hist = hist;
|
|
Me@50
|
47 return idx;
|
|
Me@50
|
48 }
|
|
Me@50
|
49
|
|
Me@50
|
50 void
|
|
Me@50
|
51 VMS_impl__record_interval_start_in_probe( int32 probeID )
|
|
Me@50
|
52 { IntervalProbe *probe;
|
|
Me@50
|
53
|
|
Me@50
|
54 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
55 probe->startStamp = getTSCount();
|
|
Me@50
|
56 }
|
|
Me@50
|
57
|
|
Me@50
|
58 void
|
|
Me@50
|
59 VMS_impl__record_interval_end_in_probe( int32 probeID )
|
|
Me@50
|
60 { IntervalProbe *probe;
|
|
Me@50
|
61 TSCount endStamp;
|
|
Me@50
|
62
|
|
Me@50
|
63 endStamp = getTSCount();
|
|
Me@50
|
64
|
|
Me@50
|
65 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
66 probe->endStamp = endStamp;
|
|
Me@50
|
67
|
|
Me@50
|
68 if( probe->hist != NULL )
|
|
Me@50
|
69 { TSCount interval = probe->endStamp - probe->startStamp;
|
|
Me@50
|
70 //if the interval is sane, then add to histogram
|
|
Me@50
|
71 if( interval < probe->hist->endOfRange * 10 )
|
|
Me@50
|
72 addToFloatHist( interval, probe->hist );
|
|
Me@50
|
73 }
|
|
Me@50
|
74 }
|
|
Me@50
|
75
|
|
Me@50
|
76 void
|
|
Me@50
|
77 VMS_impl__print_stats_of_probe( int32 probeID )
|
|
Me@50
|
78 { IntervalProbe *probe;
|
|
Me@50
|
79
|
|
Me@50
|
80 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
81
|
|
Me@50
|
82 if( probe->hist == NULL )
|
|
Me@50
|
83 {
|
|
Me@50
|
84 printf("probe: %s, interval: %.6lf\n", probe->nameStr,probe->interval);
|
|
Me@50
|
85 }
|
|
Me@50
|
86
|
|
Me@50
|
87 else
|
|
Me@50
|
88 {
|
|
Me@50
|
89 printf( "probe: %s\n", probe->nameStr );
|
|
Me@50
|
90 printFloatHist( probe->hist );
|
|
Me@50
|
91 }
|
|
Me@50
|
92 }
|
|
Me@50
|
93 #else
|
|
Me@50
|
94 #ifdef STATS__USE_DBL_PROBES
|
|
Me@50
|
95
|
|
Me@50
|
96 /*
|
|
Me@50
|
97 * In practice, probe operations are called from the app, from inside slaves
|
|
Me@50
|
98 * -- so have to be sure each probe is single-VP owned, and be sure that
|
|
Me@50
|
99 * any place common structures are modified it's done inside the master.
|
|
Me@50
|
100 * So -- the only place common structures are modified is during creation.
|
|
Me@50
|
101 * after that, all mods are to individual instances.
|
|
Me@50
|
102 *
|
|
Me@50
|
103 * Thniking perhaps should change the semantics to be that probes are
|
|
Me@50
|
104 * attached to the virtual processor -- and then everything is guaranteed
|
|
Me@50
|
105 * to be isolated -- except then can't take any intervals that span VPs,
|
|
Me@50
|
106 * and would have to transfer the probes to Master env when VP dissipates..
|
|
Me@50
|
107 * gets messy..
|
|
Me@50
|
108 *
|
|
Me@50
|
109 * For now, just making so that probe creation causes a suspend, so that
|
|
Me@50
|
110 * the dynamic array in the master env is only modified from the master
|
|
Me@50
|
111 *
|
|
Me@50
|
112 */
|
|
Me@50
|
113 IntervalProbe *
|
|
Me@50
|
114 create_generic_probe( char *nameStr, VirtProcr *animPr )
|
|
Me@50
|
115 { IntervalProbe *newProbe;
|
|
Me@50
|
116 VMSSemReq reqData;
|
|
Me@50
|
117
|
|
Me@50
|
118 reqData.reqType = createProbe;
|
|
Me@50
|
119 reqData.nameStr = nameStr;
|
|
Me@50
|
120
|
|
Me@52
|
121 VMS__send_VMSSem_request( &reqData, animPr );
|
|
Me@50
|
122
|
|
Me@53
|
123 return animPr->dataRetFromReq;
|
|
Me@50
|
124 }
|
|
Me@50
|
125
|
|
Me@52
|
126 /*Use this version from outside VMS -- it uses external malloc, and modifies
|
|
Me@52
|
127 * dynamic array, so can't be animated in a slave VP
|
|
Me@52
|
128 */
|
|
Me@52
|
129 IntervalProbe *
|
|
Me@52
|
130 ext__create_generic_probe( char *nameStr )
|
|
Me@52
|
131 { IntervalProbe *newProbe;
|
|
Me@52
|
132 int32 nameLen;
|
|
Me@52
|
133
|
|
Me@52
|
134 newProbe = malloc( sizeof(IntervalProbe) );
|
|
Me@52
|
135 nameLen = strlen( nameStr );
|
|
Me@52
|
136 newProbe->nameStr = malloc( nameLen );
|
|
Me@52
|
137 memcpy( newProbe->nameStr, nameStr, nameLen );
|
|
Me@52
|
138 newProbe->hist = NULL;
|
|
Me@52
|
139 newProbe->schedChoiceWasRecorded = FALSE;
|
|
Me@52
|
140 newProbe->probeID =
|
|
Me@52
|
141 addToDynArray( newProbe, _VMSMasterEnv->dynIntervalProbesInfo );
|
|
Me@52
|
142
|
|
Me@52
|
143 return newProbe;
|
|
Me@52
|
144 }
|
|
Me@52
|
145
|
|
Me@53
|
146
|
|
Me@53
|
147 /*Only call from inside master or main startup/shutdown thread
|
|
Me@53
|
148 */
|
|
Me@53
|
149 void
|
|
Me@53
|
150 VMS_impl__free_probe( IntervalProbe *probe )
|
|
Me@53
|
151 { if( probe->hist != NULL ) freeDblHist( probe->hist );
|
|
Me@53
|
152 if( probe->nameStr != NULL) VMS__free( probe->nameStr );
|
|
Me@53
|
153 VMS__free( probe );
|
|
Me@53
|
154 }
|
|
Me@53
|
155
|
|
Me@53
|
156
|
|
Me@50
|
157 int32
|
|
Me@53
|
158 VMS_impl__record_time_point_into_new_probe( char *nameStr, VirtProcr *animPr)
|
|
Me@50
|
159 { IntervalProbe *newProbe;
|
|
Me@50
|
160 struct timeval *startStamp;
|
|
Me@50
|
161 float64 startSecs;
|
|
Me@50
|
162
|
|
Me@50
|
163 newProbe = create_generic_probe( nameStr, animPr );
|
|
Me@50
|
164 newProbe->endSecs = 0;
|
|
Me@50
|
165
|
|
Me@50
|
166 gettimeofday( &(newProbe->startStamp), NULL);
|
|
Me@50
|
167
|
|
Me@50
|
168 //turn into a double
|
|
Me@50
|
169 startStamp = &(newProbe->startStamp);
|
|
Me@50
|
170 startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 );
|
|
Me@50
|
171 newProbe->startSecs = startSecs;
|
|
Me@50
|
172
|
|
Me@50
|
173 return newProbe->probeID;
|
|
Me@50
|
174 }
|
|
Me@50
|
175
|
|
Me@50
|
176 int32
|
|
Me@52
|
177 VMS_ext_impl__record_time_point_into_new_probe( char *nameStr )
|
|
Me@52
|
178 { IntervalProbe *newProbe;
|
|
Me@52
|
179 struct timeval *startStamp;
|
|
Me@52
|
180 float64 startSecs;
|
|
Me@52
|
181
|
|
Me@52
|
182 newProbe = ext__create_generic_probe( nameStr );
|
|
Me@52
|
183 newProbe->endSecs = 0;
|
|
Me@52
|
184
|
|
Me@52
|
185 gettimeofday( &(newProbe->startStamp), NULL);
|
|
Me@52
|
186
|
|
Me@52
|
187 //turn into a double
|
|
Me@52
|
188 startStamp = &(newProbe->startStamp);
|
|
Me@52
|
189 startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 );
|
|
Me@52
|
190 newProbe->startSecs = startSecs;
|
|
Me@52
|
191
|
|
Me@52
|
192 return newProbe->probeID;
|
|
Me@52
|
193 }
|
|
Me@52
|
194
|
|
Me@52
|
195 int32
|
|
Me@50
|
196 VMS_impl__create_single_interval_probe( char *nameStr, VirtProcr *animPr )
|
|
Me@50
|
197 { IntervalProbe *newProbe;
|
|
Me@50
|
198
|
|
Me@50
|
199 newProbe = create_generic_probe( nameStr, animPr );
|
|
Me@50
|
200
|
|
Me@50
|
201 return newProbe->probeID;
|
|
Me@50
|
202 }
|
|
Me@50
|
203
|
|
Me@50
|
204 int32
|
|
Me@50
|
205 VMS_impl__create_histogram_probe( int32 numBins, float64 startValue,
|
|
Me@50
|
206 float64 binWidth, char *nameStr, VirtProcr *animPr )
|
|
Me@50
|
207 { IntervalProbe *newProbe;
|
|
Me@50
|
208 DblHist *hist;
|
|
Me@50
|
209
|
|
Me@50
|
210 newProbe = create_generic_probe( nameStr, animPr );
|
|
Me@50
|
211
|
|
Me@50
|
212 hist = makeDblHistogram( numBins, startValue, binWidth );
|
|
Me@50
|
213 newProbe->hist = hist;
|
|
Me@50
|
214 return newProbe->probeID;
|
|
Me@50
|
215 }
|
|
Me@50
|
216
|
|
Me@50
|
217 void
|
|
Me@50
|
218 VMS_impl__index_probe_by_its_name( int32 probeID, VirtProcr *animPr )
|
|
Me@50
|
219 { IntervalProbe *probe;
|
|
Me@50
|
220
|
|
Me@50
|
221 //TODO: fix this To be in Master -- race condition
|
|
Me@50
|
222 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
223
|
|
Me@50
|
224 addValueIntoTable(probe->nameStr, probe, _VMSMasterEnv->probeNameHashTbl);
|
|
Me@50
|
225 }
|
|
Me@50
|
226
|
|
Me@50
|
227 IntervalProbe *
|
|
Me@50
|
228 VMS_impl__get_probe_by_name( char *probeName, VirtProcr *animPr )
|
|
Me@50
|
229 {
|
|
Me@50
|
230 //TODO: fix this To be in Master -- race condition
|
|
Me@50
|
231 return getValueFromTable( probeName, _VMSMasterEnv->probeNameHashTbl );
|
|
Me@50
|
232 }
|
|
Me@50
|
233
|
|
Me@50
|
234
|
|
Me@50
|
235 /*Everything is local to the animating procr, so no need for request, do
|
|
Me@50
|
236 * work locally, in the anim Pr
|
|
Me@50
|
237 */
|
|
Me@50
|
238 void
|
|
Me@50
|
239 VMS_impl__record_sched_choice_into_probe( int32 probeID, VirtProcr *animatingPr )
|
|
Me@50
|
240 { IntervalProbe *probe;
|
|
Me@50
|
241
|
|
Me@50
|
242 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
243 probe->schedChoiceWasRecorded = TRUE;
|
|
Me@50
|
244 probe->coreNum = animatingPr->coreAnimatedBy;
|
|
Me@50
|
245 probe->procrID = animatingPr->procrID;
|
|
Me@53
|
246 probe->procrCreateSecs = animatingPr->createPtInSecs;
|
|
Me@50
|
247 }
|
|
Me@50
|
248
|
|
Me@50
|
249 /*Everything is local to the animating procr, so no need for request, do
|
|
Me@50
|
250 * work locally, in the anim Pr
|
|
Me@50
|
251 */
|
|
Me@50
|
252 void
|
|
Me@50
|
253 VMS_impl__record_interval_start_in_probe( int32 probeID )
|
|
Me@50
|
254 { IntervalProbe *probe;
|
|
Me@50
|
255
|
|
Me@54
|
256 DEBUG_MSG( dbgProbes, "record start of interval\n" )
|
|
Me@50
|
257 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
258 gettimeofday( &(probe->startStamp), NULL );
|
|
Me@50
|
259 }
|
|
Me@50
|
260
|
|
Me@50
|
261
|
|
Me@50
|
262 /*Everything is local to the animating procr, so no need for request, do
|
|
Me@50
|
263 * work locally, in the anim Pr
|
|
Me@50
|
264 */
|
|
Me@50
|
265 void
|
|
Me@50
|
266 VMS_impl__record_interval_end_in_probe( int32 probeID )
|
|
Me@50
|
267 { IntervalProbe *probe;
|
|
Me@50
|
268 struct timeval *endStamp, *startStamp;
|
|
Me@54
|
269 float64 startSecs, endSecs;
|
|
Me@50
|
270
|
|
Me@54
|
271 DEBUG_MSG( dbgProbes, "record end of interval\n" )
|
|
Me@50
|
272 //possible seg-fault if array resized by diff core right after this
|
|
Me@50
|
273 // one gets probe..? Something like that? Might be safe.. don't care
|
|
Me@50
|
274 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
275 gettimeofday( &(probe->endStamp), NULL);
|
|
Me@50
|
276
|
|
Me@50
|
277 //now turn into an interval held in a double
|
|
Me@50
|
278 startStamp = &(probe->startStamp);
|
|
Me@50
|
279 endStamp = &(probe->endStamp);
|
|
Me@50
|
280
|
|
Me@50
|
281 startSecs = startStamp->tv_sec + ( startStamp->tv_usec / 1000000.0 );
|
|
Me@50
|
282 endSecs = endStamp->tv_sec + ( endStamp->tv_usec / 1000000.0 );
|
|
Me@50
|
283
|
|
Me@50
|
284 probe->interval = endSecs - startSecs;
|
|
Me@50
|
285 probe->startSecs = startSecs;
|
|
Me@50
|
286 probe->endSecs = endSecs;
|
|
Me@50
|
287
|
|
Me@50
|
288 if( probe->hist != NULL )
|
|
Me@50
|
289 {
|
|
Me@50
|
290 //if the interval is sane, then add to histogram
|
|
Me@50
|
291 if( probe->interval < probe->hist->endOfRange * 10 )
|
|
Me@50
|
292 addToDblHist( probe->interval, probe->hist );
|
|
Me@50
|
293 }
|
|
Me@50
|
294 }
|
|
Me@50
|
295
|
|
Me@50
|
296 void
|
|
Me@50
|
297 print_probe_helper( IntervalProbe *probe )
|
|
Me@50
|
298 {
|
|
Me@50
|
299 printf( "\nprobe: %s, ", probe->nameStr );
|
|
Me@50
|
300
|
|
Me@50
|
301 if( probe->schedChoiceWasRecorded )
|
|
Me@50
|
302 { printf( "coreNum: %d, procrID: %d, procrCreated: %.6lf | ",
|
|
Me@50
|
303 probe->coreNum, probe->procrID, probe->procrCreateSecs );
|
|
Me@50
|
304 }
|
|
Me@50
|
305
|
|
Me@50
|
306 if( probe->endSecs == 0 ) //just a single point in time
|
|
Me@50
|
307 {
|
|
Me@50
|
308 printf( " time point: %.6lf\n",
|
|
Me@50
|
309 probe->startSecs - _VMSMasterEnv->createPtInSecs );
|
|
Me@50
|
310 }
|
|
Me@50
|
311 else if( probe->hist == NULL ) //just an interval
|
|
Me@50
|
312 {
|
|
Me@50
|
313 printf( " startSecs: %.6lf, interval: %.6lf\n",
|
|
Me@50
|
314 probe->startSecs - _VMSMasterEnv->createPtInSecs, probe->interval);
|
|
Me@50
|
315 }
|
|
Me@50
|
316 else //a full histogram of intervals
|
|
Me@50
|
317 {
|
|
Me@50
|
318 printDblHist( probe->hist );
|
|
Me@50
|
319 }
|
|
Me@50
|
320 }
|
|
Me@50
|
321
|
|
Me@50
|
322 //TODO: change so pass around pointer to probe instead of its array-index..
|
|
Me@50
|
323 // will eliminate chance for timing of resize to cause problems with the
|
|
Me@50
|
324 // lookup -- even though don't think it actually can cause problems..
|
|
Me@50
|
325 // there's no need to pass index around -- have hash table for names, and
|
|
Me@50
|
326 // only need it once, then have ptr to probe.. the thing about enum the
|
|
Me@50
|
327 // index and use that as name is clunky in practice -- just hash.
|
|
Me@50
|
328 void
|
|
Me@50
|
329 VMS_impl__print_stats_of_probe( int32 probeID )
|
|
Me@50
|
330 { IntervalProbe *probe;
|
|
Me@50
|
331
|
|
Me@50
|
332 probe = _VMSMasterEnv->intervalProbes[ probeID ];
|
|
Me@50
|
333
|
|
Me@50
|
334 print_probe_helper( probe );
|
|
Me@50
|
335 }
|
|
Me@50
|
336
|
|
Me@50
|
337
|
|
Me@50
|
338
|
|
Me@50
|
339 void
|
|
Me@50
|
340 generic_print_probe( void *_probe )
|
|
Me@50
|
341 { IntervalProbe *probe;
|
|
Me@50
|
342
|
|
Me@50
|
343 probe = (IntervalProbe *)_probe;
|
|
Me@50
|
344 print_probe_helper( probe );
|
|
Me@50
|
345 }
|
|
Me@50
|
346
|
|
Me@50
|
347 void
|
|
Me@50
|
348 VMS_impl__print_stats_of_all_probes()
|
|
Me@50
|
349 { IntervalProbe *probe;
|
|
Me@50
|
350
|
|
Me@50
|
351 forAllInDynArrayDo( _VMSMasterEnv->dynIntervalProbesInfo,
|
|
Me@50
|
352 &generic_print_probe );
|
|
Me@50
|
353 fflush( stdout );
|
|
Me@50
|
354 }
|
|
Me@50
|
355 #endif
|
|
Me@50
|
356 #endif
|
|
Me@50
|
357
|
|
Me@50
|
358 /* Junk left over from when trying the different ways to get time stamps..
|
|
Me@50
|
359 struct timeval tim;
|
|
Me@50
|
360 gettimeofday(&tim, NULL);
|
|
Me@50
|
361 double t1=tim.tv_sec+(tim.tv_usec/1000000.0);
|
|
Me@50
|
362
|
|
Me@50
|
363 clock_t startClockStamp = clock();
|
|
Me@50
|
364
|
|
Me@50
|
365 TSCount startMultStamp = getTSCount();
|
|
Me@50
|
366 */
|
|
Me@50
|
367
|
|
Me@50
|
368 /*
|
|
Me@50
|
369 TSCount endMultStamp = getTSCount();
|
|
Me@50
|
370
|
|
Me@50
|
371 dividerParams->numTSCsToExe = endMultStamp - startMultStamp;
|
|
Me@50
|
372 printf("\ntime to execute: %d\n", endMultStamp - startMultStamp);
|
|
Me@50
|
373
|
|
Me@50
|
374 //==================================================================
|
|
Me@50
|
375 clock_t endClockStamp = clock();
|
|
Me@50
|
376 printf("%.4lf seconds of processing\n",
|
|
Me@50
|
377 (endClockStamp - startClockStamp)/(double)CLOCKS_PER_SEC);
|
|
Me@50
|
378
|
|
Me@50
|
379 //==================================================================
|
|
Me@50
|
380 gettimeofday(&tim, NULL);
|
|
Me@50
|
381 double t2=tim.tv_sec+(tim.tv_usec/1000000.0);
|
|
Me@50
|
382 printf("%.6lf seconds elapsed\n", t2-t1);
|
|
Me@50
|
383 */
|