Mail Archives: djgpp-workers/2002/10/16/07:21:30
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 -