>From d1160ec6d239b2e0f20c2fb3395e3b70963bf916 Mon Sep 17 00:00:00 2001
From: Paul Eggert
Date: Thu, 7 Jan 2016 21:28:23 -0800
Subject: [PATCH 1/2] grep: improve unibyte -P performance
This is a followon to the recent changes prompted by Bug#20526.
In Norihiro Tanaka pointed out
that grep mistakenly assumed that unibyte locales cannot have
encoding errors. Here, the mistake hurt performance significantly.
On Fedora 23 x86-64 in the C locale, this patch improved grep's
performance by a factor of 7 when run as "grep -P 'z.*a'" on the
output of "yes $(printf '\200\n') | head -n 1000000000".
* src/pcresearch.c (multibyte_locale) [HAVE_LIBPCRE]: New static var.
(Pcompile): Set it.
(Pexecute): Use it to avoid the need to call
buf_has_encoding_errors in unibyte locales.
---
src/pcresearch.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)
diff --git a/src/pcresearch.c b/src/pcresearch.c
index c0b8678..1fae94d 100644
--- a/src/pcresearch.c
+++ b/src/pcresearch.c
@@ -84,6 +84,8 @@ jit_exec (char const *subject, int search_bytes, int search_offset,
/* Table, indexed by ! (flag & PCRE_NOTBOL), of whether the empty
string matches when that flag is used. */
static int empty_match[2];
+
+static bool multibyte_locale;
#endif
void
@@ -104,10 +106,14 @@ Pcompile (char const *pattern, size_t size)
char const *p;
char const *pnul;
- if (using_utf8 ())
- flags |= PCRE_UTF8;
- else if (MB_CUR_MAX != 1)
- error (EXIT_TROUBLE, 0, _("-P supports only unibyte and UTF-8 locales"));
+ if (1 < MB_CUR_MAX)
+ {
+ if (! using_utf8 ())
+ error (EXIT_TROUBLE, 0,
+ _("-P supports only unibyte and UTF-8 locales"));
+ multibyte_locale = true;
+ flags |= PCRE_UTF8;
+ }
/* FIXME: Remove these restrictions. */
if (memchr (pattern, '\n', size))
@@ -194,12 +200,16 @@ Pexecute (char *buf, size_t size, size_t *match_size,
error. */
char const *subject = buf;
- /* If the input is free of encoding errors a multiline search is
+ /* If the input is unibyte or is free of encoding errors a multiline search is
typically more efficient. Otherwise, a single-line search is
typically faster, so that pcre_exec doesn't waste time validating
the entire input buffer. */
- bool multiline = ! buf_has_encoding_errors (buf, size - 1);
- buf[size - 1] = eolbyte;
+ bool multiline = true;
+ if (multibyte_locale)
+ {
+ multiline = ! buf_has_encoding_errors (buf, size - 1);
+ buf[size - 1] = eolbyte;
+ }
for (; p < buf + size; p = line_start = line_end + 1)
{
--
2.5.0