|
Home > Archive > Unix Programming > December 2004 > Regarding localtime(3)
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Regarding localtime(3)
|
|
| Nick Patavalis 2004-12-19, 5:48 pm |
| I have a program in which many parts, many functions, need to get the
system-time in broken-down (``struct tm``) format, quite
often. Normally each function would do something like this: ::
struct tm *tm;
time_t t;
t = time(NULL);
tm = localtime(&t);
But I'm worried about the performance impact of this. I guess, and I
may be wrong, that ``localtime()`` is quite an expensive function,
with all the calendarian calculations it has to perform. So I'm
leaning towards using a ``get_time()`` functions that, in a way,
caches the results of the time-calculations. Something like this: ::
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
struct tm *
get_time (void)
{
static struct tm ref_tm;
static time_t ref_time;
static time_t endofday = 0;
time_t now;
now = time(NULL);
if ( ! endofday || now >= endofday ) {
localtime_r(&now, &ref_tm);
ref_time = now;
endofday = ( (60 * 60 * 24)
- ( (ref_tm.tm_hour * 60 * 60)
+ (ref_tm.tm_min * 60 )
+ (ref_tm.tm_sec) ) );
endofday += ref_time;
} else {
time_t dt;
dt = now - ref_time;
if ( dt ) {
dt += ref_tm.tm_sec;
ref_tm.tm_sec = dt % 60;
dt = ref_tm.tm_min + dt / 60;
ref_tm.tm_min = dt % 60;
ref_tm.tm_hour += dt / 60;
ref_time = now;
}
}
return &ref_tm;
}
My question is: Will I see any performance difference using
``get_time()``, or does ``localtime()`` do something like this
internally anyway?
Any comments and suggestion are welcome.
Thanks in advance
/npat
| |
| Måns Rullgård 2004-12-19, 5:48 pm |
| Nick Patavalis <npat@efault.net> writes:
> I have a program in which many parts, many functions, need to get the
> system-time in broken-down (``struct tm``) format, quite
> often. Normally each function would do something like this: ::
>
> struct tm *tm;
> time_t t;
>
> t = time(NULL);
> tm = localtime(&t);
>
> But I'm worried about the performance impact of this. I guess, and I
> may be wrong, that ``localtime()`` is quite an expensive function,
> with all the calendarian calculations it has to perform. So I'm
> leaning towards using a ``get_time()`` functions that, in a way,
> caches the results of the time-calculations. Something like this: ::
[...]
> My question is: Will I see any performance difference using
> ``get_time()``, or does ``localtime()`` do something like this
> internally anyway?
>
> Any comments and suggestion are welcome.
Run the program in your favorite profiler, and see if localtime() is
anything close to a bottleneck. Unless you call it *very* often (many
times per second), I doubt it will be a problem.
--
Måns Rullgård
mru@inprovide.com
| |
| Nick Landsberg 2004-12-19, 8:46 pm |
| M=E5ns Rullg=E5rd wrote:
> Nick Patavalis <npat@efault.net> writes:
>=20
>=20
>=20
>=20
> [...]
>=20
>=20
>=20
>=20
> Run the program in your favorite profiler, and see if localtime() is
> anything close to a bottleneck. Unless you call it *very* often (many
> times per second), I doubt it will be a problem.
>=20
There is at least one flavor of Solaris where the performance
of localtime() is directly related to the timezone you are in
(or so I have heard). From what I've heard, it varied from
about 50 microseconds to 500 miroseconds on a 1 Ghz box.
YMMV. Do the measurements that M=E5ns suggests.
NPL
--=20
"It is impossible to make anything foolproof
because fools are so ingenious"
- A. Bloch
| |
| Nick Patavalis 2004-12-19, 8:46 pm |
| On 2004-12-20, Nick Landsberg <SPAMhukolauTRAP@SPAMworldnetTRAP.att.net> wrote:
>
> Måns Rullgård wrote:
>
> There is at least one flavor of Solaris where the performance
> of localtime() is directly related to the timezone you are in
> (or so I have heard). From what I've heard, it varied from
> about 50 microseconds to 500 miroseconds on a 1 Ghz box.
>
> YMMV. Do the measurements that Måns suggests.
>
Ok, I did some measurements. I measured the time it takes to execute
this: ::
for (i = 0; i < 1000000; i++)
tm = get_time();
Versus the time it takes to execute this: ::
for (i = 0; i < 1000000; i++) {
t = time(NULL);
tm = localtime(&t);
}
The results were: 1.120898 sec for the first case (``get_time()``),
and 2.150889 sec for the second (``localtime``). Which seems to
indicate that localtime does some sort of caching, or other clever
tricks.
Then I measured the time it takes for a single ``localtime()`` call to
complete. It seems that *the first call* takes about 104usec, while
*the following* take something like 3 or 4 usec. This seems to
reinforce my assumption that ``localtime()`` does some sort of
caching.
Does anyone know how modern "localtime"s are implemented?
/npat
P.S. Measurements were on a Linux box, with glibc-2.3.2
| |
| Nick Landsberg 2004-12-20, 2:47 am |
| Nick Patavalis wrote:
> On 2004-12-20, Nick Landsberg <SPAMhukolauTRAP@SPAMworldnetTRAP.att.net=
> wrote:
>=20
[vbcol=seagreen]
>=20
>=20
> Ok, I did some measurements. I measured the time it takes to execute
> this: ::
>=20
> for (i =3D 0; i < 1000000; i++)
> tm =3D get_time();
>=20
> Versus the time it takes to execute this: ::
>=20
> for (i =3D 0; i < 1000000; i++) {
> t =3D time(NULL);
> tm =3D localtime(&t);
> }
>=20
> The results were: 1.120898 sec for the first case (``get_time()``),
> and 2.150889 sec for the second (``localtime``). Which seems to
> indicate that localtime does some sort of caching, or other clever
> tricks.
>=20
> Then I measured the time it takes for a single ``localtime()`` call to
> complete. It seems that *the first call* takes about 104usec, while
> *the following* take something like 3 or 4 usec. This seems to
> reinforce my assumption that ``localtime()`` does some sort of
> caching.
>=20
> Does anyone know how modern "localtime"s are implemented?
>=20
> /npat
>=20
> P.S. Measurements were on a Linux box, with glibc-2.3.2
Great! You did the measurements 
Now, the arithmetic ...
If you are executing localtime() say 1000 times per second,
you will be "chewing up" about 4 milliseconds of CPU during
thos subsequent calls to localtime(). Is that 0.4% significant to your
application?
Putting it another way, if you're running (say) a transaction
processing application, would the additional 4 usecs impact
the response time?
If you're looking for performance improvements, look to the
interactions of major modules rather than trying to optimize
low-level routines. (Czeslanki's second law of optimization.
The first law is left as an exercise.
NPL
P.S.:
No, I don't know how modern localtime() routines are implemented
but your code fragment in another post is probably close.
--=20
"It is impossible to make anything foolproof
because fools are so ingenious"
- A. Bloch
| |
| Nick Patavalis 2004-12-20, 8:47 pm |
| Nick Landsberg wrote:
> Nick Patavalis wrote:
>
>
> If you are executing localtime() say 1000 times per second,
> you will be "chewing up" about 4 milliseconds of CPU during
> thos subsequent calls to localtime(). Is that 0.4% significant to your
> application?
>
Certainly not. But if a call to localtime takes about 104usec (as the
*first* call does), then for 1000 calls per second (which is not very
far from what my program will do) this is 104msec or about 10% of the
time. This *is* significant.
>
> P.S.:
> No, I don't know how modern localtime() routines are implemented
> but your code fragment in another post is probably close.
>
That's my point. If localtime() does some sort of "caching" like this,
then there is no reason to optimize. If it doesn't, then there
probably is.
/npat
| |
|
| Nick Patavalis wrote:
> Nick Landsberg wrote:
>
>
> Certainly not. But if a call to localtime takes about 104usec (as the
> *first* call does), then for 1000 calls per second (which is not very
> far from what my program will do) this is 104msec or about 10% of the
> time. This *is* significant.
>
>
>
>
> That's my point. If localtime() does some sort of "caching" like this,
> then there is no reason to optimize. If it doesn't, then there
> probably is.
Just a thought, but try working the stats out for calling localtime(),
then WAITING and doing other things. I'd be surprised if the impl has
any caching, its probably just the OS optimizing code as it runs (right
chunks are in cache). You want to know if localtime() has the same
performance a) when you go localtime() (wait, do stuff) localtime() and
b) localtime() (do complicated stuff) localtime(). I suspect you'll
find the nice 2/3 ms calls will grow... possibly quite a lot.
(You have to ask, WHY is the first time so slow? Is the library being
loaded? Is some kind of file data being accessed? If so, when these
calls aren't used for a while it will go back to the idle state and
the first call will be slow again...)
ciao,
Doug.
| |
| Geoff Clare 2004-12-21, 5:56 pm |
| Doug <doug@null.com> wrote, on Tue, 21 Dec 2004 09:47:46 +0800:
> (You have to ask, WHY is the first time so slow? Is the library being
> loaded? Is some kind of file data being accessed? If so, when these
> calls aren't used for a while it will go back to the idle state and
> the first call will be slow again...)
The first call has to obtain timezone information for the zone
specified by the TZ environment variable (unless a previous
time-related function has already obtained it). Depending on the
value of TZ this may involve reading the information from files.
Calling tzset() before starting the timing would mean the
first localtime() call doesn't need to do this task. (This
assumes the implementation caches the timezone information and
only obtains it again if TZ changes.)
--
Geoff Clare <netnews@gclare.org.uk>
|
|
|
|
|