Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 31 Oct 2001 11:47:28 -0800
From:      Bakul Shah <bakul@bitblocks.com>
To:        Peter Jeremy <peter.jeremy@alcatel.com.au>
Cc:        Poul-Henning Kamp <phk@critter.freebsd.dk>, Peter Wemm <peter@wemm.org>, arch@FreeBSD.ORG
Subject:   Re: 64 bit times revisited.. 
Message-ID:  <200110311947.OAA05182@devonshire.cnchost.com>
In-Reply-To: Your message of "Wed, 31 Oct 2001 16:37:41 %2B1100." <20011031163741.C85128@gsmx07.alcatel.com.au> 

next in thread | previous in thread | raw e-mail | index | archive | help
> >> >Okay, how about this?  Define N types that will be
> >> >*exactly* the same on *all* machines:
> >> >
> >> >    time_t	 32 bits	(1 second resolution, upto yr 2038)
> >> >    nstime64_t	 64 bits	(10^-9 second resolution, upto yr 2554)
> >> 
> >> Should be 1/2^32 resolution or you have a math nightmare dividing
> >> by 1000000000 all the time.
> >
> >On my 500Mhz PIII it takes about 4.6ns to divide a 64 bit
> >number by a 64 bit 10^9.
> 
> Are you sure?  I've just _measured_ it on a PIII-600 and came up with
> 211nsec (averaged over 1e7 loops).  Keep in mind that this solution
> has to also work in embedded applications - which are several orders
> of magnitude slower than this.  

Dang!  My number is bogus:-(  The best number I get is about
130ns on a 533Mhz PIII.  Test source code included below.  I
am not sure what the bug was in the original code....  But
the point remains that this is not a math nighmare or all
that expensive even on a slow machine.

BTW, strtoll or strtoq don't seem to work for reading long
long numbers!

> There are two logical timestamp formats for a binary computer:

s/logical/convenient/.

> 1) Fixed point seconds with M bits to the left of the binary
>    point and N bits to the right.
> 2) Integral number of (fractional second units).  (As used on
>    the IBM System 360 and later).

My vote is for 2), where the fractional unit is 10^-9 seconds
and I called it `nstime64_t'.  I don't like fixed point.  You
may as well use floating point like long double since most
processors these days have very good floating point
performance but then it won't make the embedded system folks
happy.

There have been over 100 messages on this subject in the past
few days and rather than respond to individual messages I
will summarize my (evolved) view below one more time!  Please
prefix IMHO to every point!

- converting to 64 bit time_t in a piecemeal fashion is not
  worth it at this point.
  - The sky is not to falling down until 2038!
  - Let us use some of that time in coming up with a
    compromise that works across the board as this problem
    afflicts almost *all* variants of Unix, including the
    ones on 64 bit platform.
  - The issue is *what* that compromise will be and that
    requires thinking through the implications of changes (as
    opposed to having some free time to code up a solution).
  - I am certainly not suggesting waiting till the last
    moment or even years to fix the problem.

- time_t doesn't have to be closely tied to a processor's
  native integer type -- it just has to be some arithmetic
  type so arguments about 64 bit time_t on a 64 bit platform
  (and by implication, 256 bit time_t on 256 bit platform)
  are weak.

- I am advocating a 64 bit type with a nanosecond resolution
  and 584 years of span as a reasonable compromise type:
  - a 64 bit time_t with a second resolution is an overkill;
    it is way more than the expected life of universe!
  - very few applications require resolution less than 1ns.
  - 584 years is a long enough time -- we can not even
    imagine what computers will be like in 100 years.
  BTW, a signed representation will cut this in half to
  292 years, which is still good enough.

  Note this is just a proposal and I have not thought through
  all of its implications (for example, on struct tm).  It
  may be that we need a more radical solution such a 128 bit
  type as PHK & other advocate or a long double or something.

- Just moving to a second resolution 64 bit time_t will
  mean there will be a lot of inertia against doing anything
  better.

- Dealing with standards bodies is a pain but we do heed
  standards in FreeBSD and sooner or later POSIX will have to
  face this issue at which point if FreeBSD solution is
  different we will end up having to replicate a bunch of
  things. [It may be that POSIX won't be able to agree on
  anything more that 64 bit time_t but I am not so
  pessimistic!]

- I am comfortable with a parallel set of system/library
  calls for any new time type if that means old programs
  don't have to recompiled to read, e.g. old dump tapes or
  create them for old machines.

- The issue of what the kernel uses internally is separate.
  As long as the kernel's representation can be mapped to
  time_t (or its descendent) we are fine.

- what a filesystem uses for timestamping files is related
  but I do not see how UFS1 can be made to stretch beyond
  2038.  As for UFS2 or some other fs, a sufficiently general
  time type may remove the need for timeval or timespec and
  there needs to be mapping between a file timestamp and
  time_t (at least for the limited life of a computer) but
  why constrain them any more?

- It is true that frivolous topics like C style cause long
  drawn-out arguments but the converse is not true; this is
  not a `bikeshed' issue.

Once again, all in my humble opinion!

-- bakul

#include <stdio.h>
#include <sys/time.h>

long long f(long long x, long long y);
long long g(long long x, long long y);
int
main(int argc, char**argv)
{
	long long x = strtoll(a[1], 0, 10);
	long long y = strtoll(a[2], 0, 10);
	long long z;
	unsigned long count = strtoul(a[3], 0, 0);
	int i;
	struct timeval t0, t1, t2;
	double d0, d1, d2;
	
	/* make x bigger since we can't read > 32 bit numbers with strtoll */
	x *= x;
	printf("x=%lld, y=%lld, count=%ld\n", x, y, count);

	gettimeofday(&t0, 0);
	for (i = 0; i < count; i++)
		z = f(x, y);
	gettimeofday(&t1, 0);
	/* t1 - t0 == overhead time */

	for (i = 0; i < count; i++)
		z = g(x, y);
	gettimeofday(&t2, 0);
	/* t2 - t1 == overhead + count divides time */

	d0 = t0.tv_sec*1E9 + t0.tv_usec*1E3;
	d1 = t1.tv_sec*1E9 + t1.tv_usec*1E3;
	d2 = t2.tv_sec*1E9 + t2.tv_usec*1E3;
	printf("%g\n", (d2-d1-(d1-d0))/count);
	exit(0);
}

long long
f(long long x, long long y)
{
	return x;
}

long long
g(long long x, long long y)
{
	return x / y;
}

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110311947.OAA05182>