grep: cache userdiff_driver in grep_source
authorJeff King <peff@peff.net>
Thu, 2 Feb 2012 08:20:43 +0000 (03:20 -0500)
committerJunio C Hamano <gitster@pobox.com>
Thu, 2 Feb 2012 18:36:08 +0000 (10:36 -0800)
Right now, grep only uses the userdiff_driver for one thing:
looking up funcname patterns for "-p" and "-W". As new uses
for userdiff drivers are added to the grep code, we want to
minimize attribute lookups, which can be expensive.

It might seem at first that this would also optimize multiple
lookups when the funcname pattern for a file is needed
multiple times. However, the compiled funcname pattern is
already cached in struct grep_opt's "priv" member, so
multiple lookups are already suppressed.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
grep.c
grep.h
diff --git a/grep.c b/grep.c
index 2a3fe7ce6fd9ad8afd38190362c3a622ad8526a3..bb1856985b673a3a57cf2aaad8c82d5de2abd521 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -841,12 +841,9 @@ static int match_funcname(struct grep_opt *opt, struct grep_source *gs, char *bo
 {
        xdemitconf_t *xecfg = opt->priv;
        if (xecfg && !xecfg->find_func) {
-               struct userdiff_driver *drv;
-               grep_attr_lock();
-               drv = userdiff_find_by_path(gs->name);
-               grep_attr_unlock();
-               if (drv && drv->funcname.pattern) {
-                       const struct userdiff_funcname *pe = &drv->funcname;
+               grep_source_load_driver(gs);
+               if (gs->driver->funcname.pattern) {
+                       const struct userdiff_funcname *pe = &gs->driver->funcname;
                        xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
                } else {
                        xecfg = opt->priv = NULL;
@@ -1237,6 +1234,7 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
        gs->name = name ? xstrdup(name) : NULL;
        gs->buf = NULL;
        gs->size = 0;
+       gs->driver = NULL;
 
        switch (type) {
        case GREP_SOURCE_FILE:
@@ -1340,3 +1338,15 @@ int grep_source_load(struct grep_source *gs)
        }
        die("BUG: invalid grep_source type");
 }
+
+void grep_source_load_driver(struct grep_source *gs)
+{
+       if (gs->driver)
+               return;
+
+       grep_attr_lock();
+       gs->driver = userdiff_find_by_path(gs->name);
+       if (!gs->driver)
+               gs->driver = userdiff_find_by_name("default");
+       grep_attr_unlock();
+}
diff --git a/grep.h b/grep.h
index 8bf3001417144815aef57db751a0762daf8a34a8..73b28c2df7ca4c9c6e29c759e11a5fb55cfbb7b9 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -9,6 +9,7 @@ typedef int pcre_extra;
 #endif
 #include "kwset.h"
 #include "thread-utils.h"
+#include "userdiff.h"
 
 enum grep_pat_token {
        GREP_PATTERN,
@@ -141,6 +142,8 @@ struct grep_source {
 
        char *buf;
        unsigned long size;
+
+       struct userdiff_driver *driver;
 };
 
 void grep_source_init(struct grep_source *gs, enum grep_source_type type,
@@ -148,6 +151,7 @@ void grep_source_init(struct grep_source *gs, enum grep_source_type type,
 int grep_source_load(struct grep_source *gs);
 void grep_source_clear_data(struct grep_source *gs);
 void grep_source_clear(struct grep_source *gs);
+void grep_source_load_driver(struct grep_source *gs);
 
 int grep_source(struct grep_opt *opt, struct grep_source *gs);