[Info-vax] High resolution per-process CPU consumption statistics

Mark Daniel mark.daniel at wasd.vsm.com.au
Sat Mar 28 18:46:52 EDT 2020


On 29/3/20 9:01 am, Mark Daniel wrote:
8< snip 8<
> The actual code keeps a history (array) of up-to 8 code-points (of which 
> the following output snippet showd two in use).  The actual routine is 
> too complex to post here but here are examples of some of the numbers 
> coming out.
8< snip 8<

Well, perhaps, have a code review.

Embedded in the WASD server.

> /*****************************************************************************/
> /*
> This is a development tool.
> 
> OpenVMS System Services Reference Manual (V8.4): $RPCC_64:
> 
> "On Alpha and I64 systems, returns a 64-bit long version of the current process
> cycle counter.  On Alpha systems, this service must be called at least once
> within each wrap period of the least significant 32 bits of the counter.  For
> more information, see the RPCC() C-language built-in documentation and the RPCC
> instruction in the Alpha Architecture Handbook."
> 
> The Alpha Architecture Book (1992):
> 
> "The low-order 32 bits of the process cycle counter is an unsigned 32-bit
> integer that increments once per N CPU cycles, where N is an implementation-
> specific integer in the range 1..16.  The cycle counter frequency is the number
> of times the process cycle counter gets incremented per second, rounded to a
> 64-bit integer.  The integer count wraps to 0 from a count of FFFF FFFF16?  The
> counter wraps no more frequently than 1.5 times the implementation's interval
> clock interrupt period (which is two thirds of the interval clock interrupt
> frequency).  The high-order 32 bits of the process cycle counter are an offset
> that when added to the low-order 32 bits gives the cycle count for this
> process.  The process cycle counter is suitable for timing intervals on the
> order of nanoseconds and may be used for detailed performance characterization.
> It is required on all implementations.  PCC is required for every processor,
> and each processor in a multiprocessor system has its own private, independent
> PCC."
> 
> Calls to this function need to be embedded into code between points measuring
> CPU clock counts.  Up to eight such measurements may concurrently be performed. 
> The |index| parameter is used to specify 1..8.  This calculates a delta with
> the previous value (from reset or previous call), reports that and the
> percentage of total counts.  The same |index| value but negative resets that
> count and reports the same.  If |index| is zero all elements are reinitialised
> to the current CPU count.
> 
> Not quite convinced the is as useful as originally hoped but as it was a bit of
> a tease to get working, and does not chew code in a production environment,
> will leave in place for possible future use.
> */
> 
> #if WATCH_MOD
> 
> #ifndef __VAX
> 
> unsigned __int64 WatchRPCC
> (
> NETIO_STRUCT *ioptr,
> int index,
> char *module,
> int line
> )
> {
> #define INDEX_MAX 8
> 
>    static int  watching;
>    static unsigned __int64  ctx64, init64;
>    static unsigned __int64  delta64 [INDEX_MAX+1],
>                             prev64 [INDEX_MAX+1];
> 
>    int  bsize, cnt, idx;
>    ushort  slen;
>    unsigned __int64  drpcc64, rpcc64;
>    double  fpercent;
>    char  *bptr;
>    char  buf [256],
>          pbuf [32];
>    REQUEST_STRUCT  *rqptr;
> 
>    /*********/
>    /* begin */
>    /*********/
> 
>    /* apparently the context is unnecessary but innocuous from Alpha V8.4 */
>    rpcc64 = sys$rpcc_64 (&ctx64);
> 
>    if (index == 0 || !init64)
>    {
>       /* initialise */
>       init64 = rpcc64;
>       for (idx = 0; idx < INDEX_MAX+1; idx++) prev64[idx] = rpcc64;
>       /* enable RPCC WATCHing is logical name exists */
>       bptr = SysTrnLnm ("WASD_WATCH_RPCC");
>       watching = 0;
>       if (bptr) watching = atoi(bptr);
>       if (index == 0) return (0);
>    }
> 
>    if (index > INDEX_MAX || -index > INDEX_MAX)
>       ErrorExitVmsStatus (SS$_BUGCHECK, ErrorSanityCheck, FI_LI);
> 
>    /* then reset this array element to the current count */
>    if (index < 0) prev64[-index] = rpcc64;
> 
>    if (watching)
>    {
>       cnt = 0;
>       drpcc64 = rpcc64 - init64;
>       for (idx = 0; idx < INDEX_MAX+1; idx++)
>       {
>          if (prev64[idx] == init64)
>             delta64[idx] = 0;
>          else
>          {
>             delta64[idx] = rpcc64 - prev64[idx];
>             cnt++;
>          }
>       }
>       bptr = buf;
>       bsize = sizeof(buf)-2;
>       FaoToBuffer (bptr, bsize, &slen, "RPCC !SL !&, at SQ", index, &drpcc64);
>       bptr += slen;
>       bsize -= slen;
>       for (idx = 0; idx < cnt; idx++)
>       {
>          if (idx > 0)
>             fpercent = ((double)delta64[idx] * 100.0) / (double)delta64[0];
>          else
>             fpercent = ((double)delta64[0] * 100.0) / (double)drpcc64;
>          sprintf (pbuf, "(%.1f%%)", fpercent);
>          FaoToBuffer (bptr, bsize, &slen, " [!UL]!&, at SQ!AZ",
>                       idx, &delta64[idx], pbuf);
>          bptr += slen;
>          bsize -= slen;
>       }
> 
>       if (ioptr)
>          if (WATCHING (ioptr, WATCH_REQUEST))
>             WatchThis (ioptr->WatchItem, module, line, WATCH_REQUEST,
>                        "!AZ", buf);
> 
>       if (watching > 0)
>          FaoToStdout ("|!%T !8AZ !4ZL|!AZ\n", 0, module, line, buf);
>    }
> 
>    prev64[index] = prev64[0] = rpcc64;
> 
>    return (rpcc64);
> }
> 
> #else /* __VAX */
> 
> ulong WatchRPCC
> (
> NETIO_STRUCT *ioptr,
> int index,
> char *module,
> int line
> )
> {
>    return (0);
> }
> 
> #endif /* __VAX */
> 
> #endif /* WATCH_MOD */
> 
> /*****************************************************************************/



More information about the Info-vax mailing list