home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso
/
altsrc
/
articles
/
11120
< prev
next >
Wrap
Internet Message Format
|
1994-08-15
|
4KB
Path: wupost!psuvax1!news.pop.psu.edu!news.cac.psu.edu!howland.reston.ans.net!cs.utexas.edu!convex!news.duke.edu!godot.cc.duq.edu!toads.pgh.pa.us!hudson.lm.com!ivory.lm.com!not-for-mail
From: devin@telerama.lm.com (Tod McQuillin)
Newsgroups: alt.sources
Subject: Caching mktime(3)
Date: 15 Aug 1994 02:01:47 -0400
Organization: Telerama Public Access Internet, Pittsburgh, PA USA
Lines: 113
Message-ID: <32n0cb$afh@ivory.lm.com>
NNTP-Posting-Host: ivory.lm.com
The mktime(3) that comes with BSD net-2 is pretty inefficient; it
seems to do a binary search of the entire time_t space to find the
result. I discovered this while profiling an invoice generation
program; over half the CPU time was spent in mktime()!
Since most of the dates I was converting were within a one month
period, the easiest way to speed it up seemed to be to keep an MRU
cache of the midnights of the dates in question. The program could
find the time_t of the midnight of the date in the cache and then add
on the hours, minutes and seconds.
One bug: the cache will grow needlessly each time you look up the
epoch. I didn't look up the epoch, so this didn't affect me.
This approach worked; the percent time spent in mktime() dropped from
over 60% to barely significant (< 1%). Here are the results; just
call caching_mktime() instead of mktime():
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# date.h
# mktime.c
#
echo x - date.h
sed 's/^X//' >date.h << 'END-of-date.h'
Xtime_t caching_mktime(struct tm *tm);
X
X#define MINUTE 60
X#define HOUR (MINUTE * 60)
X#define DAY (HOUR * 24)
X
X#define HOURS(time) ((time) / HOUR)
X#define MINUTES(time) (((time) - HOURS(time) * HOUR) / MINUTE)
END-of-date.h
echo x - mktime.c
sed 's/^X//' >mktime.c << 'END-of-mktime.c'
X#include <sys/types.h>
X#include <time.h>
X#include <stdlib.h>
X#include <sysexits.h>
X#include <stdio.h>
X#include "date.h"
X
Xtypedef struct cache cache_t;
X
Xstruct cache {
X struct tm tment;
X time_t secs;
X cache_t *next;
X};
X
Xstatic cache_t *mru_cache = NULL;
Xstatic int hits = 0, misses = 0, lookups = 0;
X
Xtime_t cache_lookup(struct tm *tm)
X{
X cache_t *gaze, *save = 0;
X
X for (gaze = mru_cache; gaze; save = gaze, gaze = gaze->next) {
X if (gaze->tment.tm_mday == tm->tm_mday &&
X gaze->tment.tm_mon == tm->tm_mon &&
X gaze->tment.tm_year == tm->tm_year) {
X if (gaze != mru_cache) {
X save->next = gaze->next;
X gaze->next = mru_cache;
X mru_cache = gaze;
X }
X hits++;
X return gaze->secs;
X }
X }
X misses++;
X return 0;
X}
X
Xtime_t caching_mktime(struct tm *tm)
X{
X struct tm midnight;
X time_t retv;
X
X lookups++;
X midnight = *tm;
X midnight.tm_sec = midnight.tm_min = midnight.tm_hour = 0;
X if ((retv = cache_lookup(&midnight)) == 0) {
X cache_t *cache_ent;
X
X if ((cache_ent = malloc(sizeof(cache_t))) == 0) {
X fprintf(stderr, "Out of memory\n");
X exit(EX_OSERR);
X }
X retv = mktime(&midnight);
X cache_ent->tment = *tm;
X cache_ent->secs = retv;
X cache_ent->next = mru_cache;
X mru_cache = cache_ent;
X }
X return retv + tm->tm_hour * HOUR + tm->tm_min * MINUTE + tm->tm_sec;
X}
X
Xvoid cache_stats(void)
X{
X printf("Caching mktime stats: %d lookups, %d hits, %d misses\n",
X lookups, hits, misses);
X}
X
END-of-mktime.c
exit