sfeed

Simple RSS and Atom feed parser
git clone https://git.sinitax.com/codemadness/sfeed
Log | Files | Refs | README | LICENSE | Upstream | sfeed.txt

commit f18f4818ed2c992aa9b7b91c74bb9ce7cc1bc745
parent c1b44cf790f8090ff25a2ff268c3f7a8d53e1bcf
Author: Hiltjo Posthuma <hiltjo@codemadness.org>
Date:   Sun, 10 Jan 2021 16:57:53 +0100

optimize converting UNIX timestamp to localtime

Make a huge difference (cuts the time in half to process the same amount of
lines) on atleast glibc 2.30 on Void Linux.  Seems to make no difference on
OpenBSD.

- This removes atleast one heap allocation per line (checked with valgrind).
  This is because glibc will strdup() the environment variable $TZ and free it
  each time, which is pointless here and wasteful.
- localtime_r does not require to set the variables like tzname.

In glibc-2.30/time/tzset.c in __tz_convert is the following code and comment:

  /* Update internal database according to current TZ setting.
     POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
     This is a good idea since this allows at least a bit more parallelism.  */
  tzset_internal (tp == &_tmbuf && use_localtime);

This makes it always tzset() and inspect the environment $TZ etc. While with
localtime_r it will only initialize it once:

	static void tzset_internal (int always) {
	[...]
	if (is_initialized && !always)
		return;

Diffstat:
Msfeed_frames.c | 4++--
Msfeed_gopher.c | 4++--
Msfeed_html.c | 4++--
Msfeed_plain.c | 4++--
4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/sfeed_frames.c b/sfeed_frames.c @@ -20,7 +20,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) char *fields[FieldLast]; ssize_t linelen; unsigned int isnew; - struct tm *tm; + struct tm rtm, *tm; time_t parsedtime; /* menu if not unnamed */ @@ -42,7 +42,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) parsedtime = 0; if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) && - (tm = localtime(&parsedtime))) { + (tm = localtime_r(&parsedtime, &rtm))) { isnew = (parsedtime >= comparetime) ? 1 : 0; totalnew += isnew; f->totalnew += isnew; diff --git a/sfeed_gopher.c b/sfeed_gopher.c @@ -41,7 +41,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) char *fields[FieldLast], *itemhost, *itemport, *itempath; ssize_t linelen; unsigned int isnew; - struct tm *tm; + struct tm rtm, *tm; time_t parsedtime; int itemtype; @@ -81,7 +81,7 @@ printfeed(FILE *fpitems, FILE *fpin, struct feed *f) parsedtime = 0; if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) && - (tm = localtime(&parsedtime))) { + (tm = localtime_r(&parsedtime, &rtm))) { isnew = (parsedtime >= comparetime) ? 1 : 0; f->totalnew += isnew; diff --git a/sfeed_html.c b/sfeed_html.c @@ -19,7 +19,7 @@ static void printfeed(FILE *fp, struct feed *f) { char *fields[FieldLast]; - struct tm *tm; + struct tm rtm, *tm; time_t parsedtime; unsigned int isnew; ssize_t linelen; @@ -42,7 +42,7 @@ printfeed(FILE *fp, struct feed *f) parsedtime = 0; if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) && - (tm = localtime(&parsedtime))) { + (tm = localtime_r(&parsedtime, &rtm))) { isnew = (parsedtime >= comparetime) ? 1 : 0; totalnew += isnew; f->totalnew += isnew; diff --git a/sfeed_plain.c b/sfeed_plain.c @@ -16,7 +16,7 @@ static void printfeed(FILE *fp, const char *feedname) { char *fields[FieldLast]; - struct tm *tm; + struct tm rtm, *tm; time_t parsedtime; ssize_t linelen; @@ -27,7 +27,7 @@ printfeed(FILE *fp, const char *feedname) parsedtime = 0; if (!strtotime(fields[FieldUnixTimestamp], &parsedtime) && - (tm = localtime(&parsedtime))) { + (tm = localtime_r(&parsedtime, &rtm))) { if (parsedtime >= comparetime) fputs("N ", stdout); else