diff --git a/src/ca/caDiagnostics.h b/src/ca/caDiagnostics.h index f7732763a..19d6dbd2f 100644 --- a/src/ca/caDiagnostics.h +++ b/src/ca/caDiagnostics.h @@ -1,7 +1,10 @@ enum appendNumberFlag {appendNumber, dontAppendNumber}; -int catime (char *channelName, enum appendNumberFlag appNF); +int catime (char *channelName, unsigned channelCount, enum appendNumberFlag appNF); int acctst (char *pname); +#define CATIME_OK 0 +#define CATIME_ERROR -1 + diff --git a/src/ca/catime.c b/src/ca/catime.c index 8bdae96bb..dfdae01a8 100644 --- a/src/ca/catime.c +++ b/src/ca/catime.c @@ -27,251 +27,21 @@ #define LOCAL static #endif -#define CATIME_OK 0 - #ifndef NULL #define NULL 0 #endif -#ifndef min -#define min(A,B) ((A)>(B)?(B):(A)) -#endif - -#ifndef NELEMENTS -#define NELEMENTS(A) (sizeof (A) / sizeof ((A) [0])) -#endif - -#if defined(vxWorks) || defined(VMS) -#define ITERATION_COUNT 1000 -#else -#define ITERATION_COUNT 10000 -#endif - #define WAIT_FOR_ACK typedef struct testItem { - chid chix; - char name[40]; - int type; - int count; + chid chix; + char name[40]; + int type; + int count; union db_access_val val; -}ti; +} ti; -ti itemList[ITERATION_COUNT]; - - -typedef void tf (ti *pItems, unsigned iterations, unsigned *pInlineIter); - -LOCAL void test ( - ti *pItems, - unsigned iterations -); - -LOCAL void printSearchStat(unsigned iterations); - -LOCAL tf test_pend; -LOCAL tf test_search; -LOCAL tf test_sync_search; -LOCAL tf test_free; -LOCAL tf test_wait; -LOCAL tf test_put; -LOCAL tf test_wait; -LOCAL tf test_get; - -LOCAL void measure_get_latency (ti *pItems, unsigned iterations); - -void timeIt( - tf *pfunc, - ti *pItem, - unsigned iterations, - unsigned nBytes -); - - -/* - * catime () - */ -int catime (char *channelName, enum appendNumberFlag appNF) -{ - long i; - unsigned strsize; - unsigned nBytes; - - SEVCHK (ca_task_initialize(),"Unable to initialize"); - - if (appNF==appendNumber) { - printf("Testing with %lu channels named %snnn\n", - (unsigned long) NELEMENTS(itemList), channelName); - } - else { - printf("Testing with %lu channels named %s\n", - (unsigned long) NELEMENTS(itemList), channelName); - } - - strsize = sizeof(itemList[i].name)-1; - nBytes = 0; - for (i=0; ichix); - X += retry; - XX += retry*retry; - if (retry>max) { - max = retry; - } - if (retry0.0) { - printf ("Elapsed Per Item = %12.8f sec, %10.1f Items per sec", - delay/(iterations*inlineIter), (iterations*inlineIter)/delay); - if ( pItems != NULL ) { - printf(", %3.1f Mbps\n", - (inlineIter*nBytes*CHAR_BIT)/(delay*1e6)); - } - else { - printf ("\n"); - } - } - else { - printf ("Elapsed Per Item = %12.8f sec\n", - delay/(iterations*inlineIter)); - } -} +typedef void tf ( ti *pItems, unsigned iterations, unsigned *pInlineIter ); /* * test_pend() @@ -547,8 +317,6 @@ unsigned *pInlineIter *pInlineIter = 10; } - - /* * test_wait () */ @@ -622,3 +390,190 @@ LOCAL void measure_get_latency (ti *pItems, unsigned iterations) mean, stdDev, min, max); } +/* + * printSearchStat() + */ +LOCAL void printSearchStat ( const ti *pi, unsigned iterations ) +{ + unsigned i; + double X = 0u; + double XX = 0u; + double max = DBL_MIN; + double min = DBL_MAX; + double mean; + double stdDev; + + for ( i = 0; i < iterations; i++ ) { + double retry = ca_search_attempts ( pi[i].chix ); + X += retry; + XX += retry * retry; + if ( retry > max ) { + max = retry; + } + if ( retry < min ) { + min = retry; + } + } + + mean = X / iterations; + stdDev = sqrt( XX / iterations - mean * mean ); + printf ( "Search tries per chan - mean=%f std dev=%f min=%f max=%f\n", + mean, stdDev, min, max); +} + +/* + * timeIt () + */ +void timeIt ( tf *pfunc, ti *pItems, unsigned iterations, unsigned nBytes ) +{ + TS_STAMP end_time; + TS_STAMP start_time; + double delay; + unsigned inlineIter; + + tsStampGetCurrent (&start_time); + (*pfunc) (pItems, iterations, &inlineIter); + tsStampGetCurrent (&end_time); + delay = tsStampDiffInSeconds (&end_time, &start_time); + if (delay>0.0) { + printf ("Elapsed Per Item = %12.8f sec, %10.1f Items per sec", + delay/(iterations*inlineIter), (iterations*inlineIter)/delay); + if ( pItems != NULL ) { + printf(", %3.1f Mbps\n", + (inlineIter*nBytes*CHAR_BIT)/(delay*1e6)); + } + else { + printf ("\n"); + } + } + else { + printf ("Elapsed Per Item = %12.8f sec\n", + delay/(iterations*inlineIter)); + } +} + +/* + * test () + */ +LOCAL void test ( + ti *pItems, + unsigned iterations +) +{ + unsigned nBytes; + + printf ("\tasync put test\n"); + nBytes = (sizeof(caHdr) + OCT_ROUND(dbr_size[pItems[0].type])) * iterations; + timeIt (test_put, pItems, iterations, nBytes); + + printf ("\tasync get test\n"); + nBytes = (2 * sizeof(caHdr) + OCT_ROUND(dbr_size[pItems[0].type])) * (iterations/2); + timeIt (test_get, pItems, iterations/2, nBytes); + + printf ("\tsynch get test\n"); + nBytes = (2 * sizeof(caHdr) + OCT_ROUND(dbr_size[pItems[0].type])) * (iterations/100); + timeIt (test_wait, pItems, iterations/100, nBytes); +} + +/* + * catime () + */ +int catime ( char *channelName, unsigned channelCount, enum appendNumberFlag appNF ) +{ + unsigned i; + unsigned strsize; + unsigned nBytes; + ti *pItemList; + + pItemList = calloc ( channelCount, sizeof (ti) ); + if ( ! pItemList ) { + return -1; + } + + SEVCHK ( ca_task_initialize(),"Unable to initialize" ); + + if ( appNF == appendNumber ) { + printf ( "Testing with %u channels named %snnn\n", + channelCount, channelName ); + } + else { + printf ( "Testing with %lu channels named %s\n", + channelCount, channelName ); + } + + strsize = sizeof ( pItemList[0].name ) - 1; + nBytes = 0; + for ( i=0; i < channelCount; i++ ) { + if ( appNF == appendNumber ) { + sprintf ( pItemList[i].name,"%.*s%lu", + (int) (strsize - 15u), channelName, i ); + } + else { + strncpy ( pItemList[i].name, channelName, strsize); + } + pItemList[i].name[strsize]= '\0'; + pItemList[i].count = 1; + nBytes += OCT_ROUND ( strlen ( pItemList[i].name ) ) + 2 * sizeof (caHdr); + } + + printf ("search test\n"); + timeIt (test_search, pItemList, channelCount, nBytes); + printSearchStat ( pItemList, channelCount ); + + printf ( + "channel name=%s, native type=%d, native count=%lu\n", + ca_name (pItemList[0].chix), + ca_field_type (pItemList[0].chix), + ca_element_count (pItemList[0].chix)); + + printf ("\tpend event test\n"); + timeIt (test_pend, NULL, 100, 0); + + for ( i = 0; i < channelCount; i++ ) { + pItemList[i].val.fltval = 0.0f; + pItemList[i].type = DBR_FLOAT; + } + printf ( "float test\n" ); + test ( pItemList, channelCount ); + + for ( i = 0; i < channelCount; i++ ) { + pItemList[i].val.fltval = 0.0f; + pItemList[i].type = DBR_DOUBLE; + } + printf ( "double test\n" ); + test ( pItemList, channelCount ); + + for ( i = 0; i < channelCount; i++ ) { + strcpy ( pItemList[i].val.strval, "0.0" ); + pItemList[i].type = DBR_STRING; + } + printf ( "string test\n" ); + test ( pItemList, channelCount ); + + for ( i = 0; i < channelCount; i++ ) { + pItemList[i].val.intval = 0; + pItemList[i].type = DBR_INT; + } + printf ( "integer test\n" ); + test ( pItemList, channelCount ); + + printf ( "round trip jitter test\n" ); + for ( i = 0; i < channelCount; i++ ) { + pItemList[i].val.fltval = 0.0f; + pItemList[i].type = DBR_DOUBLE; + } + measure_get_latency ( pItemList, channelCount ); + + printf ("free test\n"); + timeIt ( test_free, pItemList, channelCount, 0 ); + + SEVCHK ( ca_task_exit (), "Unable to free resources at exit" ); + + free ( pItemList ); + + return CATIME_OK; +} + + + + diff --git a/src/ca/catimeMain.c b/src/ca/catimeMain.c index fb8b3bc58..d6362c769 100644 --- a/src/ca/catimeMain.c +++ b/src/ca/catimeMain.c @@ -3,23 +3,31 @@ #include "caDiagnostics.h" +static const unsigned defaultIterations = 10000u; + int main(int argc, char **argv) { - char *pname; + const char *pUsage = " [ []]"; - if(argc <= 1 || argc>3){ -printf("usage: %s []\n", - argv[0]); - return -1; - } - else{ - pname = argv[1]; - if (argc==3) { - catime(pname, appendNumber); + if ( argc > 1 ) { + char *pname = argv[1]; + if ( argc > 2 ) { + int iterations = atoi (argv[2]); + if ( iterations > 0) { + if ( argc > 3 ) { + if ( argc == 4 ) { + return catime ( pname, (unsigned) iterations, appendNumber ); + } + } + else { + return catime ( pname, (unsigned) iterations, dontAppendNumber ); + } + } } else { - catime(pname, dontAppendNumber); + return catime ( pname, defaultIterations, dontAppendNumber ); } } - return 0; + printf ( "usage: %s %s\n", argv[0], pUsage); + return -1; }