On Fri, Jul 29, 2022 at 08:13:14AM -0500, Scott Cheloha wrote:
> On Wed, Jul 13, 2022 at 12:50:24AM -0500, Scott Cheloha wrote:
> > We reduce overhead if we only parse the user's format string once. To
> > achieve that, this patch does the following:
> >
> > [...]
> >
> > - When parsing the user format string in fmtfmt(), keep a list of
> > where each microsecond substring lands in buf. We'll need it later.
> >
> > - Move the printing part of fmtfmt() into a new function, fmtprint().
> > fmtprint() is now called from the main loop instead of fmtfmt().
> >
> > - In fmtprint(), before calling strftime(3), update any microsecond
> > substrings in buf using the list we built earlier in fmtfmt(). Note
> > that if there aren't any such substrings we don't call snprintf(3)
> > at all.
> >
> > [...]
>
> Two week bump.
>
> Here is a stripped-down patch with only the above changes. Hopefully
> this makes the intent of the patch more obvious.
Four week bump + rebase.
Index: ts.c
===================================================================
RCS file: /cvs/src/usr.bin/ts/ts.c,v
retrieving revision 1.9
diff -u -p -r1.9 ts.c
--- ts.c 3 Aug 2022 16:54:30 -0000 1.9
+++ ts.c 10 Aug 2022 17:49:53 -0000
@@ -17,6 +17,7 @@
*/
#include <sys/types.h>
+#include <sys/queue.h>
#include <sys/time.h>
#include <err.h>
@@ -27,13 +28,20 @@
#include <unistd.h>
#include <time.h>
+SIMPLEQ_HEAD(, usec) usec_queue = SIMPLEQ_HEAD_INITIALIZER(usec_queue);
+struct usec {
+ SIMPLEQ_ENTRY(usec) next;
+ char *pos;
+};
+
static char *format = "%b %d %H:%M:%S";
static char *buf;
static char *outbuf;
static size_t bufsize;
static size_t obsize;
-static void fmtfmt(const struct timespec *);
+static void fmtfmt(void);
+static void fmtprint(const struct timespec *);
static void __dead usage(void);
int
@@ -90,6 +98,8 @@ main(int argc, char *argv[])
if ((outbuf = calloc(1, obsize)) == NULL)
err(1, NULL);
+ fmtfmt();
+
/* force UTC for interval calculations */
if (iflag || sflag)
if (setenv("TZ", "UTC", 1) == -1)
@@ -108,7 +118,7 @@ main(int argc, char *argv[])
timespecadd(&now, &utc_offset, &ts);
else
ts = now;
- fmtfmt(&ts);
+ fmtprint(&ts);
if (iflag)
start = now;
}
@@ -134,15 +144,11 @@ usage(void)
* so you can format while you format
*/
static void
-fmtfmt(const struct timespec *ts)
+fmtfmt(void)
{
- struct tm *tm;
- char *f, us[7];
-
- if ((tm = localtime(&ts->tv_sec)) == NULL)
- err(1, "localtime");
+ char *f;
+ struct usec *u;
- snprintf(us, sizeof(us), "%06ld", ts->tv_nsec / 1000);
strlcpy(buf, format, bufsize);
f = buf;
@@ -161,12 +167,34 @@ fmtfmt(const struct timespec *ts)
f[0] = f[1];
f[1] = '.';
f += 2;
+ u = malloc(sizeof u);
+ if (u == NULL)
+ err(1, NULL);
+ u->pos = f;
+ SIMPLEQ_INSERT_TAIL(&usec_queue, u, next);
l = strlen(f);
memmove(f + 6, f, l + 1);
- memcpy(f, us, 6);
f += 6;
}
} while (*f != '\0');
+}
+
+static void
+fmtprint(const struct timespec *ts)
+{
+ char us[8];
+ struct tm *tm;
+ struct usec *u;
+
+ if ((tm = localtime(&ts->tv_sec)) == NULL)
+ err(1, "localtime");
+
+ /* Update any microsecond substrings in the format buffer. */
+ if (!SIMPLEQ_EMPTY(&usec_queue)) {
+ snprintf(us, sizeof(us), "%06ld", ts->tv_nsec / 1000);
+ SIMPLEQ_FOREACH(u, &usec_queue, next)
+ memcpy(u->pos, us, 6);
+ }
*outbuf = '\0';
if (*buf != '\0') {