home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 355_01 / slk1.exe / MEASURE / MEASURE.C < prev    next >
C/C++ Source or Header  |  1989-08-04  |  13KB  |  610 lines

  1. /*
  2.     Suggest appropriate values for the TIME_ADJUST constant.
  3.  
  4.     source:  measure.c
  5.     started: August 2, 1989
  6.     version: see below
  7.  
  8.     By setting the TIME_ADJUST constant to the value proposed by this
  9.     program, you should more accurate timing statistics.
  10.  
  11.     The TIME_ADJUST constant is used only in the sl_adjust() function
  12.     in Sherlock.c.  It is used to subtract the "unmeasured overhead"
  13.     caused by calling and returning from Sherlock support routines.
  14.     This program measures this "unmeasured overhead" by calling dummy
  15.     Sherlock routines and counting the ticks that result.
  16.  
  17.     WARNING: This program defines a value for sl_speed, which must match
  18.     the value of sl_speed used in sherlock.c in order for this program
  19.     to give a reasonable suggestion for the value of TIME_ADJUST.
  20.     By default, sl_speed is initialized to 55 in this file and in 
  21.     sherlock.c.  This program prints the value of sl_speed right after
  22.     signing on.
  23.  
  24.     The units of TIME_ADJUST are ticks per 1000 "average" calls to
  25.     Sherlock macros.  Since there is no way to determine exactly what
  26.     an average call really is, using TIME_ADJUST will probably not produce
  27.     perfect statistics.
  28.  
  29.     The sl_adjust() routine in sherlock.c handles the details of adjusting
  30.     the statistics based on TIME_ADJUST. The TIME_ADJUST constant does not
  31.     affect the gathering of statistics in any way, just the way that
  32.     sl_dump() reports the statistics already gathered.
  33.  
  34.     Exactly one of the constants FAR_MODEL and NEAR_MODEL should be 
  35.     #defined on the command line of this program.  The program M1.EXE
  36.     should be compiled with NEAR_MODEL #defined.  The program M2.EXE
  37.     should be compiled with FAR_MODEL #defined.
  38.  
  39.     The values reported by M1.EXE and M2.EXE will be different. Modify the
  40.     make files for the tiny, small and compact models to use the value
  41.     suggested by M1.EXE.  Modify the make files for the medium, large and
  42.     huge memory model to the value suggested by M2.EXE.  The make files
  43.     distributed with Sherlock use 0 for TIME_ADJUST, as follows:
  44.  
  45.         -DTIME_ADJUST=0        Turbo C
  46.         /DTIME_ADJUST=0        MicroSoft C
  47.     
  48.     Both M1.EXE and M2.EXE suggest two values for TIME_ADJUST,
  49.     one value for when using the preferred macros and one value for
  50.     when using the alternate macros.  Make sure to use to proper value.
  51.  
  52.     In the interest of getting the best statistics, several routines below
  53.     are passed parameters that are never used, or assign values to 
  54.     variables which are never used.  The Turbo C compiler will issue 
  55.     warnings about such matters, and those warnings can safely be ignored.
  56.     The -w-aus and -w-par compiler options are used to suppress these 
  57.     warnings in measure.mak.
  58. */
  59.  
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <process.h>
  63. #include <string.h>
  64. #include <ctype.h>
  65.  
  66. #define VERSION "August 4, 1989\n"
  67.  
  68. /*
  69.     WARNING! This value of sl_speed should match that in sherlock.c!
  70. */
  71. int sl_speed = 55;
  72. unsigned long sl_count = 0;
  73.  
  74. #define TRUE        (1)
  75. #define FALSE         (0)
  76. #define BAD_EXIT     (1)
  77.  
  78. /*
  79.     Define data structure used by the dummy Sherlock routines.
  80. */
  81. struct stat {
  82.     struct stat * next;    /* pointer to next bucket.        */
  83.     struct stat * alpha;    /* alphabetical list.            */
  84.     char *    name;        /* pointer to checkpoint name.        */
  85.     long    n_stat;        /* # of calls to macros.        */
  86.     long    n_disable;    /* # of prints to skip or 0.        */
  87.     long    n_times;    /* # of profiler ticks.            */
  88.     long    n_2times;    /* Cumulative ticks.            */
  89.       long    n_ftime;    /* single execution time. 8/3/89    */
  90.     int    trace;        /* trace flag.                */
  91. };
  92. struct stat a_list;
  93.  
  94. #define MAX_STAT 500
  95. struct stat sl__nodes [MAX_STAT];    /* Static node table.    */
  96. int cur_stat = 0;
  97.  
  98. #define MAX_BUG_LEVEL 100
  99. struct stat * call_stack [MAX_BUG_LEVEL];
  100. int sl_level = 0;
  101.  
  102. #define MAX_HASH 241
  103. struct stat * hash_tab [MAX_HASH];
  104. struct stat * wildcard = NULL;    /* Head of wildcard list.        */
  105. int     troff = FALSE;         /* TRUE if all tracing disabled.    */
  106. char *     check_s = NULL;        /* Name of current macro.        */
  107. long    disable      = 0;        /* Local disable count.         */
  108. long    g_disable = 0;        /* Global disable printing counter. */
  109.  
  110. unsigned long t_check = 0;
  111. unsigned long t_find  = 0;
  112. unsigned long t_new   = 0;
  113.  
  114. /*
  115.     Function prototypes for dummy Sherlock routines.
  116. */
  117. int sl_ret    (void);
  118. int sl_visit    (struct stat *p, int stat_flag, int entry_flag);
  119. int sl1trace    (char * name);
  120. int sl2trace    (struct stat ** h, char * name);
  121.  
  122. void        sl_check    (char *);
  123. struct stat *    sl_find        (char *, char *);
  124. int        sl_hash        (char *);
  125. int        prefix        (char *, char *);
  126. struct stat *    sl_new        (char *);
  127. void        sl_init        (char *);
  128. void        sl_cout        (char);
  129. void        sl_sout        (char *);
  130. void        sl_s2out    (char *, char *);
  131. void        sl_s3out    (char *, char *, char *);
  132. void        sl_slout    (int, char *);
  133. int        sl_visit    (struct stat *, int, int);
  134. int        has_wild    (char *);
  135. int        is_match    (char *, char *);
  136. int        strcmp_        (char *, char *);
  137. int        streq_        (char *, char *);
  138.  
  139. /*
  140.     Dummy Sherlock macros.
  141. */
  142. #define TRACEPB2(a)    {static struct stat *h=0; if(sl2trace(&h,a)) {}}
  143. #define TRACEPB1(a)    if(sl1trace(a)) {}
  144.  
  145. /*
  146.     Execute a loop 1000 times, both with and without Sherlock macros.
  147.     Report the difference in clock ticks.
  148. */
  149. main()
  150. {
  151.     int i;
  152.     unsigned long sl_fast, sl_slow;
  153.  
  154.     /* Make sure exactly one of FAR_MODEL or NEAR_MODEL is defined. */
  155.  
  156. #ifndef FAR_MODEL
  157. #ifndef NEAR_MODEL
  158.     printf("Please #define NEAR_MODEL or FAR_MODEL");
  159.     exit(BAD_EXIT);
  160. #endif
  161. #endif
  162.  
  163. #ifdef FAR_MODEL
  164. #ifdef NEAR_MODEL
  165.     printf("Please #define only one of NEAR_MODEL or FAR_MODEL");
  166.     exit(BAD_EXIT);
  167. #endif
  168. #endif
  169.  
  170.     /* Sign on. */
  171.  
  172. #ifdef NEAR_MODEL
  173.     printf("m1: %s", VERSION);
  174. #endif
  175.  
  176. #ifdef FAR_MODEL
  177.     printf("m2: %s", VERSION);
  178. #endif
  179.  
  180.     /* Print speed up factor.  */
  181.     printf("sl_speed = %d\n", sl_speed);
  182.  
  183.     sl_init("dummy version");
  184.  
  185.     /* Part I:  for preferred macros. */
  186.  
  187.     /* Calculate 1000 times the Sherlock overhead. */
  188.     sl_count = 0;
  189.     for(i = 0; i < 1000; i++) {
  190.         dummy(i);
  191.     }
  192.     sl_fast = sl_count;
  193.  
  194.     sl_count = 0;
  195.     for(i = 0; i < 1000; i++) {
  196.         TRACEPB2("count");
  197.         dummy(i);
  198.         sl_ret();
  199.     }
  200.     sl_slow = sl_count;
  201.  
  202. #if 0
  203.     printf("sl_slow: %ld, sl_fast: %ld ", sl_slow, sl_fast);
  204.     printf("t_check: %ld, t_find: %ld, t_new: %ld\n",
  205.         t_check, t_find, t_new);
  206. #endif
  207.  
  208. #ifdef FAR_MODEL
  209. printf("Set TIME_ADJUST (far code models, preferred macros) to %d\n",
  210.         (sl_slow - sl_fast));
  211. #endif
  212.  
  213. #ifdef NEAR_MODEL
  214. printf("Set TIME_ADJUST (near code models, preferred macros) to %d\n",
  215.         (sl_slow - sl_fast));
  216. #endif
  217.  
  218.     /* Part II: Alternate macros. */
  219.     t_check = 0;
  220.     t_find  = 0;
  221.     t_new   = 0;
  222.  
  223.     /* Calculate 1000 times the Sherlock overhead. */
  224.     sl_count = 0;
  225.     for(i = 0; i < 1000; i++) {
  226.         dummy(i);
  227.     }
  228.     sl_fast = sl_count;
  229.  
  230.     sl_count = 0;
  231.     for(i = 0; i < 1000; i++) {
  232.         TRACEPB1("count");
  233.         dummy(i);
  234.         sl_ret();
  235.     }
  236.     sl_slow = sl_count;
  237.  
  238. #if 0
  239.     printf("sl_slow: %ld, sl_fast: %ld ", sl_slow, sl_fast);
  240.     printf("t_check: %ld, t_find: %ld, t_new: %ld\n",
  241.         t_check, t_find, t_new);
  242. #endif
  243.  
  244. #ifdef FAR_MODEL
  245. printf("Set TIME_ADJUST (far code models, alternate macros) to %d\n",
  246.         (sl_slow - sl_fast));
  247. printf("Far code models: medium, large, huge. Use prffar.obj\n");
  248. #endif
  249.  
  250. #ifdef NEAR_MODEL
  251. printf("Set TIME_ADJUST (near code models, alternate macros) to %d\n",
  252.         (sl_slow - sl_fast));
  253. printf("Near code models: tiny, small, compact. Use prfnear.obj\n");
  254. #endif
  255.  
  256. }
  257.  
  258. int global_var;
  259.  
  260. /*
  261.     A do-nothing routine that may prevent some unwanted loop optimizations.
  262.     The speed of this routine does not affect the value of TIME_ADJUST.
  263. */
  264. dummy(i)
  265. int i;
  266. {
  267.     global_var++;
  268. }
  269.  
  270. /*
  271.     The following routines are taken from sherlock.c.
  272. */
  273. void
  274. sl_check(register char *s)
  275. {
  276.     register char c;
  277.     register int i;
  278.     char sbuf [40];
  279.     char *old_s;
  280.  
  281.     t_check++;
  282.  
  283.     old_s = s;
  284.  
  285.     /* Check for null string. */
  286.     if (!*s) {
  287.         /* Write the error message. */
  288.         sprintf(sbuf, "%p", s);
  289.         sl_s3out("sl_check: ", check_s, ": null string @ ");
  290.         sl_s2out(sbuf, "\n");
  291.         exit(BAD_EXIT);
  292.     }
  293.  
  294.     /* 6/27/89: allow up to 31 character names. */
  295.     for (i = 0; i < 31; i++) {
  296.         c = *s++;
  297.         if (c == '\0') {
  298.             return ;
  299.         }
  300.  
  301.         /* Allow only identifiers and wild cards. */
  302.         if (!isalnum(c) && c != '_' && c != '*' && c != '?') {
  303.             sprintf(sbuf, "%p", s);
  304.             sl_s3out("sl_check: ", check_s, ": bad character: ");
  305.             sl_cout(c);
  306.             sl_s3out(" in ", old_s, " @ ");
  307.             sl_s2out(sbuf, "\n");
  308.             exit(BAD_EXIT);
  309.         }
  310.     }
  311.     sprintf(sbuf, "%p", s);
  312.     sl_s3out("sl_check: ", check_s, ": run on argument: ");
  313.     sl_s3out(old_s, " @ ", sbuf);
  314.     sl_sout("\n");
  315.     exit(BAD_EXIT);
  316. }
  317.  
  318. struct stat *
  319. sl_find(char *macro_type, char *s)
  320. {
  321.     register int i;
  322.     register struct stat *p, *q, *node;
  323.     register int hash;
  324.  
  325.     t_find++;
  326.  
  327.     /* Update global error string. */
  328.     check_s = macro_type;
  329.  
  330.     /* Search the proper index table. */
  331.     hash = sl_hash(s);
  332.     p = hash_tab [hash];
  333.     if (p != NULL) {
  334.         i = strcmp_(s, p -> name);
  335.         if (i == 0) {
  336.             return p;
  337.         }
  338.     }
  339.         if (p == NULL || i < 0) {
  340.         sl_check(s);
  341.         node = sl_new(s);
  342.         hash_tab [hash] = node;
  343.         node -> next  = p;
  344.         node -> n_disable = disable;
  345.         return node;
  346.     }
  347.         
  348.     /* Search the list for the node. */
  349.     for (q = p, p = p -> next; p; q = p, p = p -> next) {
  350.         i = strcmp_(s, p -> name);
  351.         if (i == 0) {
  352.             return p;
  353.         }
  354.         else if (i < 0) {
  355.             break;
  356.         }
  357.     }
  358.  
  359.     /* Not found. */
  360.     sl_check(s);
  361.     node = sl_new(s);
  362.     q -> next    = node;
  363.     node -> next = p;
  364.     node -> n_disable = disable;
  365.     return node;
  366. }
  367.  
  368. int
  369. sl_hash(register char *s)
  370. {
  371.     register unsigned int hash;
  372.  
  373.     for (hash = 0; *s; ) {
  374.         hash += hash + hash + (unsigned int) *s++;
  375.         hash %= MAX_HASH;
  376.     }
  377.     return (int) hash;
  378. }
  379.  
  380. struct stat *
  381. sl_new(char *s)
  382. {
  383.     register struct stat * node, *p;
  384.  
  385.     t_new++;
  386.  
  387.     /* Not found. Point node at a new node. */
  388.     if (cur_stat >= MAX_STAT) {
  389.         sl_sout("sl_new: trace table overflow\n");
  390.         exit(BAD_EXIT);
  391.     }
  392.  
  393.     /* Create the new node. */
  394.     node = sl__nodes + cur_stat;
  395.     cur_stat++;
  396.     node -> name  = s;
  397.     node -> n_stat = 0;
  398.     node -> n_disable = disable;
  399.  
  400.     /*
  401.         Search the wildcard list for a node which matches s.
  402.         If found.  Set trace field.
  403.     */
  404.     for (p = wildcard; p; p = p -> next) {
  405.         if (is_match(p -> name, s)) {
  406.             node -> trace = p -> trace;
  407.             return node;
  408.         }
  409.     }
  410.  
  411.     /* No match. */
  412.     node -> trace = 0;
  413.     return node;
  414. }
  415.  
  416. int
  417. has_wild(register char *s)
  418. {
  419.     register char c;
  420.  
  421.     for (;;) {
  422.         c = *s++;
  423.         if (c == '\0') {
  424.             return FALSE;
  425.         }
  426.         else if (c == '*' || c == '?') {
  427.             return TRUE;
  428.         }
  429.     }
  430. }
  431.  
  432. int
  433. is_match(register char *s1, register char *s2)
  434. {
  435.     register char c;
  436.  
  437.     for (;;) {
  438.         c = *s1++;
  439.         if (c == '\0') {
  440.             return !*s2;
  441.         }
  442.         else if (c == '*') {
  443.             /* Matches zero or more characters. */
  444.             return TRUE;
  445.         }
  446.         else if (c == '?') {
  447.             /* Matches exactly one character. */
  448.             if (*s2 == '\0') {
  449.                 return FALSE;
  450.             }
  451.             else {
  452.                 s2++;
  453.             }
  454.         }
  455.         else if (c != *s2++) {
  456.             return FALSE;
  457.         }
  458.     }
  459. }
  460.  
  461. int
  462. prefix(char *p, char *s)
  463. {
  464.     while (*p) {
  465.         if (*p++ != *s++) {
  466.             return FALSE;
  467.         }
  468.     }
  469.     return TRUE;
  470. }
  471.  
  472. int
  473. strcmp_(register char *s1, register char *s2)
  474. {
  475.     while (*s1 == *s2) {
  476.         if (*s1 == '\0') {
  477.             return 0;
  478.         }
  479.         else {
  480.             s1++;
  481.             s2++;
  482.         }
  483.     }
  484.     return ((int) *s1) - ((int) *s2);
  485. }
  486.  
  487. int
  488. streq_(register char *s1, register char *s2)
  489. {
  490.     while(*s1) {
  491.         if (*s1++ != *s2++) {
  492.             return FALSE;
  493.         }
  494.     }
  495.     return !*s2;
  496. }
  497.  
  498. void
  499. sl_init(char * version)
  500. {
  501.     int i;
  502.  
  503.     /* Initialize the hash table. */
  504.     for (i = 0; i < MAX_HASH; i++) {
  505.         hash_tab [i] = NULL;
  506.     }
  507.     a_list.alpha = NULL;
  508.     a_list.next  = NULL;
  509.     a_list.name  = NULL;
  510.  
  511.     sl_von();
  512. }
  513.  
  514. void
  515. sl_cout(char c)
  516. {
  517.     putchar(c);
  518. }
  519.  
  520. void
  521. sl_sout(char *s)
  522. {
  523.     while (*s) {
  524.         sl_cout(*s++);
  525.     }
  526. }
  527.  
  528. void
  529. sl_s2out(char *s1, char *s2)
  530. {
  531.     sl_sout(s1);
  532.     sl_sout(s2);
  533. }
  534.  
  535. void
  536. sl_s3out(char *s1, char *s2, char *s3)
  537. {
  538.     sl_sout(s1);
  539.     sl_sout(s2);
  540.     sl_sout(s3);
  541. }
  542.  
  543. /*
  544.     The following routines have been modified from
  545.     corresponding routines in sherlock.c.
  546.  
  547.     The purpose of the modifications is to measure only the
  548.     code that contributes to "unmeasured overhead."
  549.  
  550.     In the case of the preferred macros, some arbitrary guesses
  551.     have been made about the frequency of multiple calls to the
  552.     same tracepoint name, which will affect the number of times
  553.     sl_find() should be counted. If my assumptions seem unreasonable,
  554.     try your own.
  555. */
  556.  
  557. int sl_mod = 0;
  558.  
  559. /* The unmeasured portion of sl2trace. */
  560. int
  561. sl2trace(struct stat **pp, char *s)
  562. {
  563.     /* Force a call to sl_find every 5th call. */
  564.     if (sl_mod++ == 5) {
  565.         *pp = sl_find("TRACEP2", s);
  566.         sl_mod = 0;
  567.         sl_new(s);
  568.     }
  569.     sl_visit(*pp, 1, 1);
  570.     return TRUE;
  571. }
  572.  
  573. /* The unmeasured portion of sl1trace. */
  574. int
  575. sl1trace(char *s)
  576. {
  577.     struct stat * pp;
  578.  
  579.     pp = sl_find("TRACEP1", s);
  580.  
  581.     /* Force a call to sl_new every 5th call. */
  582.     if (sl_mod++ == 5) {
  583.         sl_mod = 0;
  584.         sl_new(s);
  585.     }
  586.     sl_visit(pp, 1, 1);
  587.     return TRUE;
  588. }
  589.  
  590. /* The unmeasured portion of sl_visit */
  591. int
  592. sl_visit(struct stat *p, int stat_flag, int entry_flag)
  593. {
  594. }
  595.  
  596. /* The unmeasured portion of sl_ret */
  597. int
  598. sl_ret()
  599. {
  600.     if (g_disable > 0) {
  601.         ;
  602.     }
  603.     else if (g_disable > 0) {
  604.         ;
  605.     }
  606.     else {
  607.         return TRUE;
  608.     }
  609. }
  610.