grep: add --threads=<num> option and grep.threads configuration

"git grep" can now be configured (or told from the command line) how many threads to use when searching in the working tree files. Signed-off-by: Victor Leschuk <vleschuk@accesssoftek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Victor Leschuk committed Dec 15, 2015 at 18:31 UTC 89f09dd34e613394c749f69ddd74adc90cb034ca
4 files changed +44 -13
Documentation/config.txt
+4
@@ -1447,6 +1447,10 @@ grep.extendedRegexp::
1447 option is ignored when the 'grep.patternType' option is set to a value
1448 other than 'default'.
1449
1450 +grep.threads::
1451 + Number of grep worker threads to use.
1452 + See `grep.threads` in linkgit:git-grep[1] for more information.
1453 +
1454 gpg.program::
1455 Use this custom program instead of "gpg" found on $PATH when
1456 making or verifying a PGP signature. The program must support the
Documentation/git-grep.txt
+9
@@ -23,6 +23,7 @@ SYNOPSIS
23 [--break] [--heading] [-p | --show-function]
24 [-A <post-context>] [-B <pre-context>] [-C <context>]
25 [-W | --function-context]
26 + [--threads <num>]
27 [-f <file>] [-e] <pattern>
28 [--and|--or|--not|(|)|-e <pattern>...]
29 [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
@@ -53,6 +54,10 @@ grep.extendedRegexp::
54 option is ignored when the 'grep.patternType' option is set to a value
55 other than 'default'.
56
57 +grep.threads::
58 + Number of grep worker threads to use. If unset (or set to 0),
59 + 8 threads are used by default (for now).
60 +
61 grep.fullName::
62 If set to true, enable '--full-name' option by default.
63
@@ -227,6 +232,10 @@ OPTIONS
232 effectively showing the whole function in which the match was
233 found.
234
235 +--threads <num>::
236 + Number of grep worker threads to use.
237 + See `grep.threads` in 'CONFIGURATION' for more information.
238 +
239 -f <file>::
240 Read patterns from <file>, one per line.
241
builtin/grep.c
+30 -13
@@ -24,11 +24,11 @@ static char const * const grep_usage[] = {
24 NULL
25 };
26
27 -static int use_threads = 1;
27 +#define GREP_NUM_THREADS_DEFAULT 8
28 +static int num_threads;
29
30 #ifndef NO_PTHREADS
30 -#define THREADS 8
31 -static pthread_t threads[THREADS];
31 +static pthread_t *threads;
32
33 /* We use one producer thread and THREADS consumer
34 * threads. The producer adds struct work_items to 'todo' and the
@@ -63,13 +63,13 @@ static pthread_mutex_t grep_mutex;
63
64 static inline void grep_lock(void)
65 {
66 - if (use_threads)
66 + if (num_threads)
67 pthread_mutex_lock(&grep_mutex);
68 }
69
70 static inline void grep_unlock(void)
71 {
72 - if (use_threads)
72 + if (num_threads)
73 pthread_mutex_unlock(&grep_mutex);
74 }
75
@@ -206,7 +206,8 @@ static void start_threads(struct grep_opt *opt)
206 strbuf_init(&todo[i].out, 0);
207 }
208
209 - for (i = 0; i < ARRAY_SIZE(threads); i++) {
209 + threads = xcalloc(num_threads, sizeof(*threads));
210 + for (i = 0; i < num_threads; i++) {
211 int err;
212 struct grep_opt *o = grep_opt_dup(opt);
213 o->output = strbuf_out;
@@ -238,12 +239,14 @@ static int wait_all(void)
239 pthread_cond_broadcast(&cond_add);
240 grep_unlock();
241
241 - for (i = 0; i < ARRAY_SIZE(threads); i++) {
242 + for (i = 0; i < num_threads; i++) {
243 void *h;
244 pthread_join(threads[i], &h);
245 hit |= (int) (intptr_t) h;
246 }
247
248 + free(threads);
249 +
250 pthread_mutex_destroy(&grep_mutex);
251 pthread_mutex_destroy(&grep_read_mutex);
252 pthread_mutex_destroy(&grep_attr_mutex);
@@ -267,6 +270,14 @@ static int grep_cmd_config(const char *var, const char *value, void *cb)
270 int st = grep_config(var, value, cb);
271 if (git_color_default_config(var, value, cb) < 0)
272 st = -1;
273 +
274 + if (!strcmp(var, "grep.threads")) {
275 + num_threads = git_config_int(var, value);
276 + if (num_threads < 0)
277 + die(_("invalid number of threads specified (%d) for %s"),
278 + num_threads, var);
279 + }
280 +
281 return st;
282 }
283
@@ -294,7 +305,7 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1,
305 }
306
307 #ifndef NO_PTHREADS
297 - if (use_threads) {
308 + if (num_threads) {
309 add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
310 strbuf_release(&pathbuf);
311 return 0;
@@ -323,7 +334,7 @@ static int grep_file(struct grep_opt *opt, const char *filename)
334 strbuf_addstr(&buf, filename);
335
336 #ifndef NO_PTHREADS
326 - if (use_threads) {
337 + if (num_threads) {
338 add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
339 strbuf_release(&buf);
340 return 0;
@@ -702,6 +713,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
713 N_("show <n> context lines before matches")),
714 OPT_INTEGER('A', "after-context", &opt.post_context,
715 N_("show <n> context lines after matches")),
716 + OPT_INTEGER(0, "threads", &num_threads,
717 + N_("use <n> worker threads")),
718 OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
719 context_callback),
720 OPT_BOOL('p', "show-function", &opt.funcname,
@@ -832,13 +845,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
845
846 #ifndef NO_PTHREADS
847 if (list.nr || cached || show_in_pager)
835 - use_threads = 0;
848 + num_threads = 0;
849 + else if (num_threads == 0)
850 + num_threads = GREP_NUM_THREADS_DEFAULT;
851 + else if (num_threads < 0)
852 + die(_("invalid number of threads specified (%d)"), num_threads);
853 #else
837 - use_threads = 0;
854 + num_threads = 0;
855 #endif
856
857 #ifndef NO_PTHREADS
841 - if (use_threads) {
858 + if (num_threads) {
859 if (!(opt.name_only || opt.unmatch_name_only || opt.count)
860 && (opt.pre_context || opt.post_context ||
861 opt.file_break || opt.funcbody))
@@ -908,7 +925,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
925 hit = grep_objects(&opt, &pathspec, &list);
926 }
927
911 - if (use_threads)
928 + if (num_threads)
929 hit |= wait_all();
930 if (hit && show_in_pager)
931 run_pager(&opt, prefix);
contrib/completion/git-completion.bash
+1
@@ -1310,6 +1310,7 @@ _git_grep ()
1310 --full-name --line-number
1311 --extended-regexp --basic-regexp --fixed-strings
1312 --perl-regexp
1313 + --threads
1314 --files-with-matches --name-only
1315 --files-without-match
1316 --max-depth