[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