From: Brian Downing <bdowning@lavos.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org, Brian Downing <bdowning@lavos.net>
Subject: [PATCH 2/5] Bypass textual patch generation and parsing in git blame
Date: Thu, 21 Aug 2008 18:21:58 -0500 [thread overview]
Message-ID: <1219360921-28529-3-git-send-email-bdowning@lavos.net> (raw)
In-Reply-To: <1219360921-28529-2-git-send-email-bdowning@lavos.net>
This uses the new xdiff emit_func feature to directly generate the
patch/chunk information from the low-level diff output, rather than
generating and parsing a patch. This improves performance considerably
for certain test cases:
:; time git-blame -M -C -C -p --incremental server.c >/dev/null
Before:
79.62user 0.10system 1:19.81elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+41189minor)pagefaults 0swaps
After:
48.66user 0.08system 0:48.75elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (0major+36961minor)pagefaults 0swaps
Signed-off-by: Brian Downing <bdowning@lavos.net>
---
builtin-blame.c | 90 +++++++++++++++++++------------------------------------
1 files changed, 31 insertions(+), 59 deletions(-)
diff --git a/builtin-blame.c b/builtin-blame.c
index e4d12de..60f70bf 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -19,6 +19,10 @@
#include "string-list.h"
#include "mailmap.h"
#include "parse-options.h"
+#include "xdiff/xtypes.h"
+#include "xdiff/xdiffi.h"
+#include "xdiff/xemit.h"
+#include "xdiff/xmacros.h"
static char blame_usage[] = "git blame [options] [rev-opts] [rev] [--] file";
@@ -464,62 +468,36 @@ struct patch {
int num;
};
-struct blame_diff_state {
- struct patch *ret;
- unsigned hunk_post_context;
- unsigned hunk_in_pre_context : 1;
-};
-
-static void process_u_diff(void *state_, char *line, unsigned long len)
+static int process_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg)
{
- struct blame_diff_state *state = state_;
+ struct patch *patch = ecb->priv;
+ long s1, s2;
+ xdchange_t *xch, *xche;
struct chunk *chunk;
- int off1, off2, len1, len2, num;
- num = state->ret->num;
- if (len < 4 || line[0] != '@' || line[1] != '@') {
- if (state->hunk_in_pre_context && line[0] == ' ')
- state->ret->chunks[num - 1].same++;
- else {
- state->hunk_in_pre_context = 0;
- if (line[0] == ' ')
- state->hunk_post_context++;
- else
- state->hunk_post_context = 0;
- }
- return;
- }
+ for (xch = xche = xscr; xch; xch = xche->next) {
+ xche = xdl_get_hunk(xch, xecfg);
- if (num && state->hunk_post_context) {
- chunk = &state->ret->chunks[num - 1];
- chunk->p_next -= state->hunk_post_context;
- chunk->t_next -= state->hunk_post_context;
- }
- state->ret->num = ++num;
- state->ret->chunks = xrealloc(state->ret->chunks,
- sizeof(struct chunk) * num);
- chunk = &state->ret->chunks[num - 1];
- if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
- state->ret->num--;
- return;
- }
-
- /* Line numbers in patch output are one based. */
- off1--;
- off2--;
+ s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
+ s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
- chunk->same = len2 ? off2 : (off2 + 1);
+ ++patch->num;
+ patch->chunks = xrealloc(patch->chunks,
+ sizeof(struct chunk) * patch->num);
+ chunk = &patch->chunks[patch->num - 1];
+ chunk->same = s2 + XDL_MAX(xch->i1 - s1, 0);
+ chunk->p_next = xche->i1 + xche->chg1;
+ chunk->t_next = xche->i2 + xche->chg2;
+ }
- chunk->p_next = off1 + (len1 ? len1 : 1);
- chunk->t_next = chunk->same + len2;
- state->hunk_in_pre_context = 1;
- state->hunk_post_context = 0;
+ return 0;
}
static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
int context)
{
- struct blame_diff_state state;
+ struct patch *patch;
xpparam_t xpp;
xdemitconf_t xecfg;
xdemitcb_t ecb;
@@ -527,20 +505,14 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
xpp.flags = xdl_opts;
memset(&xecfg, 0, sizeof(xecfg));
xecfg.ctxlen = context;
- memset(&state, 0, sizeof(state));
- state.ret = xmalloc(sizeof(struct patch));
- state.ret->chunks = NULL;
- state.ret->num = 0;
-
- xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
+ patch = xmalloc(sizeof(struct patch));
+ patch->chunks = NULL;
+ patch->num = 0;
+ xecfg.emit_func = (void (*)())process_diff;
+ ecb.priv = patch;
+ xdi_diff(file_p, file_o, &xpp, &xecfg, &ecb);
- if (state.ret->num) {
- struct chunk *chunk;
- chunk = &state.ret->chunks[state.ret->num - 1];
- chunk->p_next -= state.hunk_post_context;
- chunk->t_next -= state.hunk_post_context;
- }
- return state.ret;
+ return patch;
}
/*
--
1.5.6.1
next prev parent reply other threads:[~2008-08-21 23:34 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-21 23:21 [PATCH 0/5] More git blame speed improvements Brian Downing
2008-08-21 23:21 ` [PATCH 1/5] Allow alternate "low-level" emit function from xdl_diff Brian Downing
2008-08-21 23:21 ` Brian Downing [this message]
2008-08-21 23:21 ` [PATCH 3/5] Always initialize xpparam_t to 0 Brian Downing
2008-08-21 23:22 ` [PATCH 4/5] Allow xdiff machinery to cache hash results for a file Brian Downing
2008-08-21 23:22 ` [PATCH 5/5] Use xdiff caching to improve git blame performance Brian Downing
2008-08-23 8:15 ` [PATCH 1/5] Allow alternate "low-level" emit function from xdl_diff René Scharfe
2008-08-23 9:03 ` Junio C Hamano
2008-08-24 8:12 ` Brian Downing
2008-09-03 22:29 ` René Scharfe
2008-10-25 13:30 ` [PATCH 1/5] blame: inline get_patch() René Scharfe
2008-10-25 13:30 ` [PATCH 2/5] Always initialize xpparam_t to 0 René Scharfe
2008-10-25 13:30 ` [PATCH 3/5] Allow alternate "low-level" emit function from xdl_diff René Scharfe
2008-10-25 13:31 ` [PATCH 4/5] add xdi_diff_hunks() for callers that only need hunk lengths René Scharfe
2008-10-25 13:31 ` [PATCH 5/5] blame: use xdi_diff_hunks(), get rid of struct patch René Scharfe
2008-10-25 19:36 ` Junio C Hamano
2008-10-26 22:20 ` René Scharfe
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1219360921-28529-3-git-send-email-bdowning@lavos.net \
--to=bdowning@lavos.net \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.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.
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 NNTP newsgroup(s).