delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2002/10/16/07:21:30

To: eliz AT is DOT elta DOT co DOT il
Cc: djgpp-workers AT delorie DOT com
References: <Pine DOT SUN DOT 3 DOT 91 DOT 1021016075252 DOT 20518B-100000 AT is>
Message-Id: <2.7.9.1D88N.H42NCC@pauzner.dnttm.ru>
From: "Leonid Pauzner" <uue AT pauzner DOT dnttm DOT ru>
Date: Wed, 16 Oct 2002 15:17:00 +0400 (MSD)
X-Mailer: dMail [Demos Mail for DOS v2.7.9]
Subject: Re: libc' ctime.c optimizations
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

16-Oct-2002 08:01 Eli Zaretskii wrote:
> On Tue, 15 Oct 2002, Leonid Pauzner wrote:

>> This will not help too much since other time functions
>> patalogically ineffective also.

mktime() was my primary target, it is used by gettimeofday() implementation.

> ``Patalogically ineffective''?  If you have proposals for more efficient
> implementation, please tell what they are.

> Can you show a design for such caching?  Specifically, how do you know
> when to invalidate the cached value(s)?

I mean a caching within an hour directly inside mktime(),
which will greatly optimize sequential calls
and leave random calls as efficient as they are now.
A simple patch attached; it also checks environ changes
and lcl_is_set inside mktime().


As of the implementation itself, we may want struct tm arithmetic,
e.g. tm_plus_day(), tm_minus_day(), tm_local2gmt(), tm_gmt2local().

After that, being in gmt zone, we calculate  tm -> time_t,
- keep seconds within a day and days from EPOCH separately
for cache purposes, using tm_diff() - a number of seconds within a day
(or hour).

We should not break the compatibility though, due to our or BSD bugs.

>> Also, since time functions usually called in present

> That's not a valid assumption.  There are many programs that call time
> functions for past and/or future dates.



diff -u -p old/ctime.c ./ctime.c
--- old/ctime.c Mon Jun 14 12:20:40 1999
+++ ./ctime.c   Wed Oct 16 14:11:02 2002
@@ -160,6 +160,15 @@ static int         tzload P((const char * name,
 static int             tzparse P((const char * name, struct state * sp,
                                int lastditch));

+/*
+    tm_diff:  if the first argument >= the second argument in time line,
+              and they corresponds to the same hour, then
+              returns a difference in seconds (>= 0),
+              or -1 otherwise.
+ */
+static int             tm_diff P((const struct tm * atmp,
+                               const struct tm * btmp));
+
 #ifdef ALL_STATE
 static struct state *lclptr;
 static struct state *gmtptr;
@@ -172,6 +181,7 @@ static struct state gmtmem;
 #define gmtptr (&gmtmem)
 #endif /* State Farm */

+static unsigned last_env_changed = 0;
 static int lcl_is_set; /* 0: no, 1: set by tzset, -1: set by tzsetwall */
 static int gmt_is_set;
 static char lcl_tzstr[512];
@@ -916,7 +926,6 @@ void
 tzset(void)
 {
   const char * name;
-  static unsigned last_env_changed = 0;

   /* If environ didn't changed since last time, don't waste time
      looking at $TZ.  */
@@ -1312,6 +1321,35 @@ tmcomp(const struct tm * const atmp, con
   return result;
 }

+
+/*
+    tm_diff:  if the first argument >= the second argument in time line,
+              and they corresponds to the same hour, then
+              returns a difference in seconds (>= 0),
+              or -1 otherwise.
+ */
+static int
+tm_diff(const struct tm * const atmp, const struct tm * const btmp)
+{
+  int diff = 0;
+
+  if ((atmp->tm_year - btmp->tm_year) != 0 ||
+      (atmp->tm_mon - btmp->tm_mon)   != 0 ||
+      (atmp->tm_mday - btmp->tm_mday) != 0 ||
+      (atmp->tm_hour - btmp->tm_hour) != 0)
+    return -1;  /* not within hour */
+
+
+  if ((atmp->tm_min - btmp->tm_min)   < 0 ||
+      (atmp->tm_sec - btmp->tm_sec)   < 0)
+    return -1;  /* wrond order */
+
+  diff =  (atmp->tm_min - btmp->tm_min)*60
+         + (atmp->tm_sec - btmp->tm_sec);
+  return diff;
+}
+
+
 static void
 tmnormalize(struct tm *tmp)
 {
@@ -1490,8 +1528,20 @@ time1(struct tm * const tmp, void (*cons
 time_t
 mktime(struct tm * tmp)
 {
+  static struct tm prev_tm;
+  static time_t    prev_res;
   struct tm save_tm = *tmp;
-  int rv = time1(tmp, localsub, 0L);
+  int rv;
+
+  /* cache, valid until we get the next hour, or reverse time order */
+  /* it is safe to keep less then an hour to not miss TZ swiching.  */
+  /* also, check there was no changes in $TZ / tzset()              */
+  if ((rv = tm_diff(tmp, &prev_tm)) >= 0  &&
+      (lcl_is_set > 0 && __environ_changed == last_env_changed))
+    return rv + prev_res;
+
+  /* full story */
+  rv = time1(tmp, localsub, 0L);
   if (rv == -1)
   {
     /* Try again, off a few hours.  This may get us out of the DST
@@ -1525,5 +1575,10 @@ mktime(struct tm * tmp)
     else
       tmnormalize(tmp);
   }
+
+  /* store in cache */
+  prev_tm = *tmp;
+  prev_res = rv;
+
   return rv;
 }

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019