summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2022-01-13 05:10:47 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2022-01-13 05:10:47 +0000
commita7af42c25ded7b4aa0c1e8846ca62b28bf4ac927 (patch)
tree08b8a170275e0c62f647d331823d449c8ac1ed11
parent061a377586ba1e506b39f3b5dd1d70675c108631 (diff)
Calling MB_CUR_MAX is much more expensive than incrementing a pointer
and than testing and printing a byte, so do it once up front rather than inside the inner loop. This speeds up rev(1) by about a factor of three for typical use cases. Performance issue found by cheloha@, but my fix is a bit simpler and more rigorous than Scott's original patch. While here, also add the missing handling for write errors (making them fatal, whereas read errors remain non-fatal and proceed to the next input file) and also avoid testing each byte twice, making the code more straightforward and more readable. In part using ideas from millert@ and martijn@. OK martijn@.
-rw-r--r--usr.bin/rev/rev.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/usr.bin/rev/rev.c b/usr.bin/rev/rev.c
index 10b5148f361..d0d258ff27b 100644
--- a/usr.bin/rev/rev.c
+++ b/usr.bin/rev/rev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rev.c,v 1.13 2016/04/10 17:06:52 martijn Exp $ */
+/* $OpenBSD: rev.c,v 1.14 2022/01/13 05:10:46 schwarze Exp $ */
/* $NetBSD: rev.c,v 1.5 1995/09/28 08:49:40 tls Exp $ */
/*-
@@ -46,13 +46,14 @@ void usage(void);
int
main(int argc, char *argv[])
{
- char *filename, *p = NULL, *t, *u;
+ char *filename, *p = NULL, *t, *te, *u;
FILE *fp;
ssize_t len;
size_t ps = 0;
- int ch, rval;
+ int ch, multibyte, rval;
setlocale(LC_CTYPE, "");
+ multibyte = MB_CUR_MAX > 1;
if (pledge("stdio rpath", NULL) == -1)
err(1, "pledge");
@@ -83,14 +84,16 @@ main(int argc, char *argv[])
if (p[len - 1] == '\n')
--len;
for (t = p + len - 1; t >= p; --t) {
- if (isu8cont(*t))
- continue;
- u = t;
- do {
- putchar(*u);
- } while (isu8cont(*(++u)));
+ te = t;
+ if (multibyte)
+ while (t > p && isu8cont(*t))
+ --t;
+ for (u = t; u <= te; ++u)
+ if (putchar(*u) == EOF)
+ err(1, "stdout");
}
- putchar('\n');
+ if (putchar('\n') == EOF)
+ err(1, "stdout");
}
if (ferror(fp)) {
warn("%s", filename);
@@ -104,7 +107,7 @@ main(int argc, char *argv[])
int
isu8cont(unsigned char c)
{
- return MB_CUR_MAX > 1 && (c & (0x80 | 0x40)) == 0x80;
+ return (c & (0x80 | 0x40)) == 0x80;
}
void