Decoding 16-bit floating point times in pacct record

Decoding 16-bit floating point times in pacct record

Post by Chris Mart » Thu, 30 Jun 1994 21:42:11



SunOS 4.1.3 process accounting record.

I can't find out how to decode these floating point numbers.

I have tried looking for the source of acctcom1 but can't find it.

I have tried brute force and ignorance:

(examples from acctcom1 output against original)
  16 bit    acctcom1 says it is:
      10 => .17
     453 => 7.55
    5528 => 92.13
   13409 => 695.60
       1111222233334444
       eeefffffffffffff
   10  0000000000010100 (0x000a)    10/8192 = 1.220703125e-3
  453  0000000111000101 (0x01c5)   453/8192 = 0.0552978515625
 5528  0001010110011000 (0x1598)  5528/8192 = 0.6748046875
13409  0011010001100001 (0x3461) 5217*8/8192= 5.0947265625

I have even tried 5528/92.13 to get a clue but it gives 60 ...

Can anybody help?

 
 
 

Decoding 16-bit floating point times in pacct record

Post by David Cle » Fri, 01 Jul 1994 00:32:11




>SunOS 4.1.3 process accounting record.

>I can't find out how to decode these floating point numbers.

Like SunOS 4.1.3 uses a comp_t which (from <sys/acct.h> is "a 3 bits
base 8 exponent, 13 bit fraction ``floating point'' number").

Turn it into an unsigned long using:

        (n & 0x1fff) << (3 * (n >> 13))

Then, if you're looking at accounted CPU time, divide by HZ (from
<sys/param.h>).

To illustrate this, the listing below gives the results you expect.

#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <stdlib.h>

main(argc, argv)
int argc;
char *argv[];
{
        int n;
        unsigned long x;

        n = strtol(argv[1], (char **)NULL, 10);
        x = (n & 0x1fff) << (3 * (n >> 13));
        printf("%d -> %lu -> %.2f\n", n, x, (float)x / HZ);

Quote:}

Cheers,
Dave.

 
 
 

Decoding 16-bit floating point times in pacct record

Post by Richard Tob » Thu, 30 Jun 1994 23:20:03



>SunOS 4.1.3 process accounting record.
>I can't find out how to decode these floating point numbers.

acct(5) says

   The type comp_t is a 3 bits base 8 exponent, 13 bit fraction
   ``floating   point''   number.

and this appears to be true.

Quote:>I have even tried 5528/92.13 to get a clue but it gives 60 ...

That *was* the clue!

Take the low order 13 bits, and multiply by 8 raised to the power of
the high order 3 bits.  This gives the time in 1/60 seconds.

The program below gives the following results:

  deacon% dec 10
  value is 0.166667
  deacon% dec 453
  value is 7.550000
  deacon% dec 5528
  value is 92.133333
  deacon% dec 13409
  value is 695.600000

#include <stdio.h>

int main(int argc, char **argv)
{
    unsigned input=atoi(argv[1]);
    int exp = input >> 13;
    int frac = input & 0x1fff;

    printf("value is %lf\n", frac * (1 << (exp * 3)) / 60.0);

    return 0;

Quote:}

-- Richard

--

On the net, no-one knows that you're a tentacle

 
 
 

Decoding 16-bit floating point times in pacct record

Post by David Pott » Fri, 01 Jul 1994 01:02:13




>SunOS 4.1.3 process accounting record.

>I can't find out how to decode these floating point numbers.

>I have tried looking for the source of acctcom1 but can't find it.

>I have tried brute force and ignorance:

>(examples from acctcom1 output against original)
>  16 bit    acctcom1 says it is:
>      10 => .17
>     453 => 7.55
>    5528 => 92.13
>   13409 => 695.60
>       1111222233334444
>       eeefffffffffffff
>   10  0000000000010100 (0x000a)    10/8192 = 1.220703125e-3
>  453  0000000111000101 (0x01c5)   453/8192 = 0.0552978515625
> 5528  0001010110011000 (0x1598)  5528/8192 = 0.6748046875
>13409  0011010001100001 (0x3461) 5217*8/8192= 5.0947265625

>I have even tried 5528/92.13 to get a clue but it gives 60 ...

>Can anybody help?

I have done this already.  These numbers have a 3 bit exponent and a 13
bit mantissa.  Here a c function that works.  The bias is needed because
some fields have a bias of 1 and some have a bias of 100.

/* The accounting records are written in a strange format, with a three
   bit power-of-8 bias-2 exponent, and 13 bit mantissa. Also, two of the times
   are in hundredths of a second, while the other quantities are not,
   so this routine accepts a bias factor to multiply the end result by.
   ------------------------------------------------------------------------- */
long
  NoSillyFormat(unsigned short s, int bias)
{
  long  value;
  int   exponent;

  /* The value is in the low order 13 bits.
     The exponent is in the high order 3 bits.
     It should be possible to use bit fields here.
     --------------------------------------------- */
  value = (s & 0x1FFF) * bias;
  exponent = (s >> 13) & 0x7;

  /* Portability -- shifts by negative amounts aren't,
     so here we do the right shifts to get the right answer.
   --------------------------------------------------------- */
  while (exponent > 2)
    {
      value <<= 3;
      --exponent;
    }
  while (exponent < 2)
    {
      value >>= 3;
      ++exponent;
    }
  return value;

Quote:}

--
David Potter, Open System Performance, Inc., (916)987-7531

 
 
 

Decoding 16-bit floating point times in pacct record

Post by Chris Tor » Fri, 01 Jul 1994 06:29:42





answers:

Quote:>... Here a c function that works.
>  /* The value is in the low order 13 bits.
>     The exponent is in the high order 3 bits.
>     It should be possible to use bit fields here.

Using bitfields would be unwise (they change bit order virtually
at random on different machines---often they follow the machine's
native byte order, but there is no such guarantee).

The following is from my new manpage, intended for the next BSDI release.
(This text contains embedded underlines; many newsreaders handle this
correctly.)

     The various _ c_ o_ m_ p_ __ t fields are encoded as described above, instead of be-
     ing saved in, say, floating point.  This gives a large range in a small
     space, at a small cost in accuracy.  To convert these fields, use the
     formula:
           u = (v & 0x1fff) << (3 * (v >> 13))
     (where v is the _ c_ o_ m_ p_ __ t value and _ u is the time in units of AHZ).  The
     largest possible value is 8191 * 8^7 or 17,177,772,032 units; since it
     takes 64 units to represent a second, this value represents 268,402,688
     seconds, or approximately 8.5 years.  Note that the numbers remain exact
     until the first 8191 units (just under 128 seconds), after which the low
     three bits of the value are dropped, so values that represent between 128
     and 1023.875 seconds are only accurate to the nearest 8/64 or 1/8th of a
     second.  Another three bits disappear for each new power of 8, so values
     between 1024 and 8191 seconds are only accurate to the second, and so
     forth.  Further details can be found in Knuth vol 2.

In my copy of Knuth (2nd edition), exercise 6 on page 248 is particularly
relevant.

AHZ differs on different systems; some even use their HZ parameter instead.
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc (+1 510 549 1145)