From: "Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>, "Jeff King" <peff@peff.net>,
"Jeffrey Walton" <noloader@gmail.com>,
"Michał Kiedrowicz" <michal.kiedrowicz@gmail.com>,
"J Smith" <dark.panda@gmail.com>,
"Victor Leschuk" <vleschuk@gmail.com>,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>,
"Fredrik Kuivinen" <frekui@gmail.com>,
"Brandon Williams" <bmwill@google.com>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>
Subject: [PATCH v2 4/7] grep: add support for the PCRE v1 JIT API
Date: Sat, 13 May 2017 23:45:32 +0000 [thread overview]
Message-ID: <20170513234535.12749-5-avarab@gmail.com> (raw)
In-Reply-To: <20170513234535.12749-1-avarab@gmail.com>
Change the grep PCRE v1 code to use JIT when available. When PCRE
support was initially added in commit 63e7e9d8b6 ("git-grep: Learn
PCRE", 2011-05-09) PCRE had no JIT support, it was integrated into
8.20 released on 2011-10-21.
Enabling JIT support usually improves performance by more than
40%. The pattern compilation times are relatively slower, but those
relative numbers are tiny, and are easily made back in all but the
most trivial cases of grep. Detailed benchmarks & overview of
compilation times is at: http://sljit.sourceforge.net/pcre.html
With this change the difference in a t/perf/p7820-grep-engines.sh run
is, with just the /perl/ tests shown:
$ GIT_PERF_REPEAT_COUNT=30 GIT_PERF_LARGE_REPO=~/g/linux GIT_PERF_MAKE_OPTS='-j8 USE_LIBPCRE=YesPlease CC=~/perl5/installed/bin/gcc NO_R_TO_GCC_LINKER=YesPlease CFLAGS=-O3 LIBPCREDIR=/home/avar/g/pcre/inst LDFLAGS=-Wl,-rpath,/home/avar/g/pcre/inst/lib' ./run HEAD~ HEAD p7820-grep-engines.sh
Test HEAD~ HEAD
---------------------------------------------------------------------------------------
7820.3: perl grep how.to 0.27(1.18+0.42) 0.19(0.30+0.68) -29.6%
7820.7: perl grep ^how to 0.48(2.74+0.41) 0.21(0.64+0.55) -56.2%
7820.11: perl grep [how] to 0.47(2.56+0.47) 0.26(0.86+0.56) -44.7%
7820.15: perl grep (e.t[^ ]*|v.ry) rare 0.88(5.79+0.38) 0.26(1.06+0.54) -70.5%
7820.19: perl grep m(ú|u)lt.b(æ|y)te 0.32(1.56+0.46) 0.23(0.86+0.48) -28.1%
The conditional support for JIT is implemented as suggested in the
pcrejit(3) man page. E.g. defining PCRE_STUDY_JIT_COMPILE to 0 if it's
not present.
The implementation is relatively verbose because even if
PCRE_CONFIG_JIT is defined only a call to pcre_config() can determine
if the JIT is available, and if so the faster pcre_jit_exec() function
should be called instead of pcre_exec(), and a different (but not
complimentary!) function needs to be called to free pcre1_extra_info.
There's no graceful fallback if pcre_jit_stack_alloc() fails under
PCRE_CONFIG_JIT, instead the program will simply abort. I don't think
this is worth handling gracefully, it'll only fail in cases where
malloc() doesn't work, in which case we're screwed anyway.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
grep.c | 37 ++++++++++++++++++++++++++++++++++++-
grep.h | 6 ++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/grep.c b/grep.c
index 1157529115..accf1c45e6 100644
--- a/grep.c
+++ b/grep.c
@@ -351,6 +351,9 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
const char *error;
int erroffset;
int options = PCRE_MULTILINE;
+#ifdef PCRE_CONFIG_JIT
+ int canjit;
+#endif
if (opt->ignore_case) {
if (has_non_ascii(p->pattern))
@@ -365,9 +368,20 @@ static void compile_pcre1_regexp(struct grep_pat *p, const struct grep_opt *opt)
if (!p->pcre1_regexp)
compile_regexp_failed(p, error);
- p->pcre1_extra_info = pcre_study(p->pcre1_regexp, 0, &error);
+ p->pcre1_extra_info = pcre_study(p->pcre1_regexp, PCRE_STUDY_JIT_COMPILE, &error);
if (!p->pcre1_extra_info && error)
die("%s", error);
+
+#ifdef PCRE_CONFIG_JIT
+ pcre_config(PCRE_CONFIG_JIT, &canjit);
+ if (canjit == 1) {
+ p->pcre1_jit_stack = pcre_jit_stack_alloc(1, 1024 * 1024);
+ if (!p->pcre1_jit_stack)
+ die("BUG: Couldn't allocate PCRE JIT stack");
+ pcre_assign_jit_stack(p->pcre1_extra_info, NULL, p->pcre1_jit_stack);
+ p->pcre1_jit_on = 1;
+ }
+#endif
}
static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
@@ -378,8 +392,20 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
if (eflags & REG_NOTBOL)
flags |= PCRE_NOTBOL;
+#ifdef PCRE_CONFIG_JIT
+ if (p->pcre1_jit_on)
+ ret = pcre_jit_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
+ eol - line, 0, flags, ovector,
+ ARRAY_SIZE(ovector), p->pcre1_jit_stack);
+ else
+ ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line,
+ eol - line, 0, flags, ovector,
+ ARRAY_SIZE(ovector));
+#else
ret = pcre_exec(p->pcre1_regexp, p->pcre1_extra_info, line, eol - line,
0, flags, ovector, ARRAY_SIZE(ovector));
+#endif
+
if (ret < 0 && ret != PCRE_ERROR_NOMATCH)
die("pcre_exec failed with error code %d", ret);
if (ret > 0) {
@@ -394,7 +420,16 @@ static int pcre1match(struct grep_pat *p, const char *line, const char *eol,
static void free_pcre1_regexp(struct grep_pat *p)
{
pcre_free(p->pcre1_regexp);
+#ifdef PCRE_CONFIG_JIT
+ if (p->pcre1_jit_on) {
+ pcre_free_study(p->pcre1_extra_info);
+ pcre_jit_stack_free(p->pcre1_jit_stack);
+ } else {
+ pcre_free(p->pcre1_extra_info);
+ }
+#else
pcre_free(p->pcre1_extra_info);
+#endif
pcre_free((void *)p->pcre1_tables);
}
#else /* !USE_LIBPCRE1 */
diff --git a/grep.h b/grep.h
index 38ac82b638..14f47189f9 100644
--- a/grep.h
+++ b/grep.h
@@ -3,9 +3,13 @@
#include "color.h"
#ifdef USE_LIBPCRE1
#include <pcre.h>
+#ifndef PCRE_STUDY_JIT_COMPILE
+#define PCRE_STUDY_JIT_COMPILE 0
+#endif
#else
typedef int pcre;
typedef int pcre_extra;
+typedef int pcre_jit_stack;
#endif
#include "kwset.h"
#include "thread-utils.h"
@@ -48,7 +52,9 @@ struct grep_pat {
regex_t regexp;
pcre *pcre1_regexp;
pcre_extra *pcre1_extra_info;
+ pcre_jit_stack *pcre1_jit_stack;
const unsigned char *pcre1_tables;
+ int pcre1_jit_on;
kwset_t kws;
unsigned fixed:1;
unsigned ignore_case:1;
--
2.11.0
next prev parent reply other threads:[~2017-05-13 23:46 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-13 23:45 [PATCH v2 0/7] PCRE v2, PCRE v1 JIT, log -P & fixes Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` [PATCH v2 1/7] grep: don't redundantly compile throwaway patterns under threading Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` [PATCH v2 2/7] grep: skip pthreads overhead when using one thread Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` [PATCH v2 3/7] log: add -P as a synonym for --perl-regexp Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` Ævar Arnfjörð Bjarmason [this message]
2017-05-14 14:43 ` [PATCH v2 4/7] grep: add support for the PCRE v1 JIT API Simon Ruderich
2017-05-14 15:10 ` Ævar Arnfjörð Bjarmason
2017-05-14 15:23 ` Ævar Arnfjörð Bjarmason
2017-05-15 2:43 ` Junio C Hamano
2017-05-13 23:45 ` [PATCH v2 5/7] grep: un-break building with PCRE < 8.32 Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` [PATCH v2 6/7] grep: un-break building with PCRE < 8.20 Ævar Arnfjörð Bjarmason
2017-05-13 23:45 ` [PATCH v2 7/7] grep: add support for PCRE v2 Ævar Arnfjörð Bjarmason
-- strict thread matches above, loose matches on Subject: below --
2017-05-23 19:24 [PATCH v2 0/7] PCRE v2, PCRE v1 JIT, log -P & fixes Ævar Arnfjörð Bjarmason
2017-05-20 23:50 ` [PATCH v3 00/30] Easy to review grep & pre-PCRE changes Junio C Hamano
2017-05-23 19:24 ` [PATCH v2 4/7] grep: add support for the PCRE v1 JIT API Ævar Arnfjörð Bjarmason
2017-05-24 5:17 ` Junio C Hamano
2017-05-24 7:37 ` Ævar Arnfjörð Bjarmason
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170513234535.12749-5-avarab@gmail.com \
--to=avarab@gmail.com \
--cc=bmwill@google.com \
--cc=dark.panda@gmail.com \
--cc=frekui@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=michal.kiedrowicz@gmail.com \
--cc=noloader@gmail.com \
--cc=pclouds@gmail.com \
--cc=peff@peff.net \
--cc=vleschuk@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).