📄 timexlib.c
字号:
void timexN ( FUNCPTR func, /* function to time (optional) */ int arg1, /* first of up to 8 args to call function with */ int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8 ) { int scale; int time; int error; int nreps; int percent; /* if function specified, clear any existing functions and add this one */ if (func != NULL) { timexClrArrays (); timexAddCall (timexTimeCalls, 0, func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } /* calibrate if necessary then time calls */ if (overhead == 0) timexCal (); timexAutoTime (timexPreCalls, timexTimeCalls, timexPostCalls, &nreps, &scale, &time, &error, &percent); printErr ("timex: %d reps, time per rep = %d +/- %d (%d%%) %s\n", nreps, time, error, percent, timexScaleText [scale]); }/********************************************************************************* timexPost - specify functions to be called after timing** This routine adds or deletes functions in the list of functions to be* called immediately following the timed functions. A maximum of four* functions may be included. Up to eight arguments may be passed to each* function.** RETURNS: N/A*/void timexPost ( int i, /* function number in list (0..3) */ FUNCPTR func, /* function to be added (NULL if to be deleted) */ int arg1, /* first of up to 8 args to call function with */ int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8 ) { timexAddCall (timexPostCalls, i, func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); timexShow (); }/********************************************************************************* timexPre - specify functions to be called prior to timing** This routine adds or deletes functions in the list of functions to be* called immediately prior to the timed functions. A maximum of four* functions may be included. Up to eight arguments may be passed to each* function.** RETURNS: N/A*/void timexPre ( int i, /* function number in list (0..3) */ FUNCPTR func, /* function to be added (NULL if to be deleted) */ int arg1, /* first of up to 8 args to call function with */ int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8 ) { timexAddCall (timexPreCalls, i, func, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); timexShow (); }/********************************************************************************* timexShow - display the list of function calls to be timed** This routine displays the current list of function calls to be timed.* These lists are created by calls to timexPre(), timexFunc(), and* timexPost().** RETURNS: N/A** SEE ALSO: timexPre(), timexFunc(), timexPost()*/void timexShow (void) { printf ("\ntimex:"); printf ("\n pre-calls:\n"); timexShowCalls (timexPreCalls); printf ("\n timed calls:\n"); timexShowCalls (timexTimeCalls); printf ("\n post-calls:\n"); timexShowCalls (timexPostCalls); }/********************************************************************************* timexAddCall - enter a call in a call array** RETURNS: N/A.*/LOCAL void timexAddCall ( CALL *callArray, /* array to be altered */ int i, /* function number in list (0..3) */ FUNCPTR func, /* function to be added (NULL if to be deleted) */ int arg1, /* first of up to 8 params to call function with */ int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8 ) { if (func == NULL) func = (FUNCPTR) timexNull; /* func should be declared FUNCPTR? */ if (i >= 0 && i < MAX_CALLS) { callArray[i].func = (VOIDFUNCPTR) func; /* func should be declared FUNCPTR? */ callArray[i].arg[0] = arg1; callArray[i].arg[1] = arg2; callArray[i].arg[2] = arg3; callArray[i].arg[3] = arg4; callArray[i].arg[4] = arg5; callArray[i].arg[5] = arg6; callArray[i].arg[6] = arg7; callArray[i].arg[7] = arg8; } else printf ("timex: call number must be in range 0..%d\n", MAX_CALLS - 1); }/********************************************************************************* timexAutoTime - time specified function calls with automatic scaling** This routine performs the specified timing, dynamically increasing* the number of reps until the desired accuracy is achieved.** RETURNS: N/A.*/LOCAL void timexAutoTime ( CALL_ARRAY preCalls, /* list of functions to call before timing */ FAST CALL_ARRAY timeCalls, /* list of functions to time */ CALL_ARRAY postCalls, /* list of functions to call after timing */ int *pNreps, /* ptr where to return number of times called */ int *pScale, /* ptr where to return scale: * 0 = secs, 1 = millisecs, 2 = microsecs */ int *pTime, /* ptr where to return time per rep in above units */ int *pError, /* ptr where to return error margin in above units */ int *pPercent /* ptr where to return percent error (0..100) */ ) { FAST int reps; /* start with one rep then increase reps until it takes a long * enough interval to provide sufficient resolution */ reps = 1; timexTime (reps, preCalls, timeCalls, postCalls, pScale, pTime, pError, pPercent); while ((*pPercent > MAX_PERCENT) && ((reps < MAX_REPS) || (*pTime > 0))) { reps = reps * (*pPercent) / MAX_PERCENT; timexTime (reps, preCalls, timeCalls, postCalls, pScale, pTime, pError, pPercent); } *pNreps = reps; }/********************************************************************************* timexCal - calibrate timex by timing null functions** This routine establishes the constant per rep overhead in the timing* function.** RETURNS: N/A.*/LOCAL void timexCal (void) { int scale; int time; int error; int percent; int nreps; overhead = 0; timexAutoTime (timexNullCalls, timexNullCalls, timexNullCalls, &nreps, &scale, &time, &error, &percent); overhead = time; }/********************************************************************************* timexClrArrays - clear out function arrays** RETURNS: N/A.*/LOCAL void timexClrArrays (void) { bcopy ((char *) timexNullCalls, (char *) timexPreCalls, sizeof (timexNullCalls)); bcopy ((char *) timexNullCalls, (char *) timexTimeCalls, sizeof (timexNullCalls)); bcopy ((char *) timexNullCalls, (char *) timexPostCalls, sizeof (timexNullCalls)); }/********************************************************************************* timexMakeCalls - make function calls in specified call array** RETURNS: N/A.*/LOCAL void timexMakeCalls ( CALL_ARRAY calls /* list of functions to call */ ) { FAST int ix; FAST CALL *pCall = &calls[0]; for (ix = 0; ix < MAX_CALLS; ix++, pCall++) { (* pCall->func) (pCall->arg[0], pCall->arg[1], pCall->arg[2], pCall->arg[3], pCall->arg[4], pCall->arg[5], pCall->arg[6], pCall->arg[7]); } }/********************************************************************************* timexNull - null routine** This routine is used as a place holder for null routines in the* timing function arrays. It is used to guarantee a constant calling* overhead in each iteration.** RETURNS: N/A.*/LOCAL void timexNull (void) { }/********************************************************************************* timexScale - scale raw timing data** RETURNS: N/A.*/LOCAL void timexScale ( int ticks, /* total ticks required for all reps */ int reps, /* number of reps performed */ FAST int *pScale, /* ptr where to return scale: * 0 = secs, 1 = millisecs, 2 = microsecs */ FAST int *pTime, /* ptr where to return time per rep in above units */ int *pError, /* ptr where to return error margin in above units */ int *pPercent /* ptr where to return percent error (0..100) */ ) { FAST int scalePerSec; /* calculate time per rep in best scale */ *pScale = 0; /* start with "seconds" scale */ scalePerSec = 1; *pTime = ticks * scalePerSec / sysClkRateGet () / reps; while ((*pScale < 2) && (*pTime < 100)) { (*pScale)++; scalePerSec = scalePerSec * 1000; *pTime = ticks * scalePerSec / sysClkRateGet () / reps; } /* adjust for overhead if in microseconds scale */ if (*pScale == 2) { *pTime -= overhead; if (*pTime < 0) *pTime = 0; } /* calculate error */ *pError = scalePerSec / sysClkRateGet () / reps; if (*pTime == 0) *pPercent = 100; else *pPercent = 100 * *pError / *pTime; }/********************************************************************************* timexShowCalls - print specified call array** RETURNS: N/A.*/LOCAL void timexShowCalls ( CALL_ARRAY calls /* list of functions to be displayed */ ) { char *name; /* pointer to sym table's copy of name string */ char demangled [TIMEX_DEMANGLE_PRINT_LEN + 1]; char *nameToPrint; void *value; SYMBOL_ID symId; /* symbol identifier */ int offset; int i; int j; int arg; int ncalls = 0; for (i = 0; i < MAX_CALLS; i++) { if (calls[i].func != timexNull) { ncalls++; if ((symFindSymbol (sysSymTbl, NULL, (void *)calls[i].func, SYM_MASK_NONE, SYM_MASK_NONE, &symId) != OK) || (symNameGet (symId, &name) != OK) || (symValueGet (symId, &value) != OK)) printf (" %d: 0x%x (", i, (int)calls[i].func); else { offset = (int) calls[i].func - (int) value; nameToPrint = cplusDemangle (name, demangled, sizeof (demangled)); if (offset == 0) printf (" %d: %s (", i, nameToPrint); else printf (" %d: %s+%x (", i, nameToPrint, offset); } for (j = 0; j < MAX_ARGS; j++) { if (j != 0) printf (", "); arg = calls[i].arg[j]; if ((-9 <= arg) && (arg <= 9)) printf ("%d", arg); else printf ("0x%x", arg); } printf (")\n"); } } if (ncalls == 0) printf (" (none)\n"); }/********************************************************************************* timexTime - time a specified number of reps** RETURNS: N/A.*/LOCAL void timexTime ( FAST int reps, /* number of reps to perform */ CALL_ARRAY preCalls, /* list of functions to call before timing */ FAST CALL_ARRAY timeCalls, /* list of functions to be timed */ CALL_ARRAY postCalls, /* list of functions to call after timing */ int *pScale, /* ptr where to return scale: * 0 = secs, 1 = millisecs, 2 = microsecs */ int *pTime, /* ptr where to return time per rep in above units */ int *pError, /* ptr where to return error margin in above units */ int *pPercent /* ptr where to return percent error (0..100) */ ) { int start; int end; FAST int i; timexMakeCalls (preCalls); start = (int) tickGet (); for (i = 0; i < reps; i++) timexMakeCalls (timeCalls); end = (int) tickGet (); timexMakeCalls (postCalls); timexScale (end - start, reps, pScale, pTime, pError, pPercent); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -