@matheusbsbs / matheus-bagliano / commits / cdcab133ea
Fork 0

blame: use xdi_diff_hunks(), get rid of struct patch

Based on a patch by Brian Downing, this replaces the struct patch based code for blame passing with calls to xdi_diff_hunks(). This way we avoid generating and then parsing patches; we only let the interesting infos be passed to our callbacks instead. This makes blame a bit faster: $ blame="./git blame -M -C -C -p --incremental v1.6.0" # master $ /usr/bin/time $blame Makefile >/dev/null 1.38user 0.14system 0:01.52elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+12226minor)pagefaults 0swaps $ /usr/bin/time $blame cache.h >/dev/null 1.66user 0.13system 0:01.80elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+12262minor)pagefaults 0swaps # this patch series $ /usr/bin/time $blame Makefile >/dev/null 1.27user 0.12system 0:01.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+11836minor)pagefaults 0swaps $ /usr/bin/time $blame cache.h >/dev/null 1.52user 0.12system 0:01.70elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+12052minor)pagefaults 0swaps Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Oct 25, 2008 at 15:31 UTC cdcab133ea75e0bd5c2279ce6c5718f4af4d9a03
1 file changed +52 -139
builtin-blame.c
+52 -139
@@ -442,113 +442,6 @@ static struct origin *find_rename(struct scoreboard *sb,
442 return porigin;
443 }
444
445 -/*
446 - * Parsing of patch chunks...
447 - */
448 -struct chunk {
449 - /* line number in postimage; up to but not including this
450 - * line is the same as preimage
451 - */
452 - int same;
453 -
454 - /* preimage line number after this chunk */
455 - int p_next;
456 -
457 - /* postimage line number after this chunk */
458 - int t_next;
459 -};
460 -
461 -struct patch {
462 - struct chunk *chunks;
463 - int num;
464 -};
465 -
466 -struct blame_diff_state {
467 - struct patch *ret;
468 - unsigned hunk_post_context;
469 - unsigned hunk_in_pre_context : 1;
470 -};
471 -
472 -static void process_u_diff(void *state_, char *line, unsigned long len)
473 -{
474 - struct blame_diff_state *state = state_;
475 - struct chunk *chunk;
476 - int off1, off2, len1, len2, num;
477 -
478 - num = state->ret->num;
479 - if (len < 4 || line[0] != '@' || line[1] != '@') {
480 - if (state->hunk_in_pre_context && line[0] == ' ')
481 - state->ret->chunks[num - 1].same++;
482 - else {
483 - state->hunk_in_pre_context = 0;
484 - if (line[0] == ' ')
485 - state->hunk_post_context++;
486 - else
487 - state->hunk_post_context = 0;
488 - }
489 - return;
490 - }
491 -
492 - if (num && state->hunk_post_context) {
493 - chunk = &state->ret->chunks[num - 1];
494 - chunk->p_next -= state->hunk_post_context;
495 - chunk->t_next -= state->hunk_post_context;
496 - }
497 - state->ret->num = ++num;
498 - state->ret->chunks = xrealloc(state->ret->chunks,
499 - sizeof(struct chunk) * num);
500 - chunk = &state->ret->chunks[num - 1];
501 - if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
502 - state->ret->num--;
503 - return;
504 - }
505 -
506 - /* Line numbers in patch output are one based. */
507 - off1--;
508 - off2--;
509 -
510 - chunk->same = len2 ? off2 : (off2 + 1);
511 -
512 - chunk->p_next = off1 + (len1 ? len1 : 1);
513 - chunk->t_next = chunk->same + len2;
514 - state->hunk_in_pre_context = 1;
515 - state->hunk_post_context = 0;
516 -}
517 -
518 -static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
519 - int context)
520 -{
521 - struct blame_diff_state state;
522 - xpparam_t xpp;
523 - xdemitconf_t xecfg;
524 - xdemitcb_t ecb;
525 -
526 - memset(&xpp, 0, sizeof(xpp));
527 - xpp.flags = xdl_opts;
528 - memset(&xecfg, 0, sizeof(xecfg));
529 - xecfg.ctxlen = context;
530 - memset(&state, 0, sizeof(state));
531 - state.ret = xmalloc(sizeof(struct patch));
532 - state.ret->chunks = NULL;
533 - state.ret->num = 0;
534 -
535 - xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
536 -
537 - if (state.ret->num) {
538 - struct chunk *chunk;
539 - chunk = &state.ret->chunks[state.ret->num - 1];
540 - chunk->p_next -= state.hunk_post_context;
541 - chunk->t_next -= state.hunk_post_context;
542 - }
543 - return state.ret;
544 -}
545 -
546 -static void free_patch(struct patch *p)
547 -{
548 - free(p->chunks);
549 - free(p);
550 -}
551 -
445 /*
446 * Link in a new blame entry to the scoreboard. Entries that cover the
447 * same line range have been removed from the scoreboard previously.
@@ -795,6 +688,22 @@ static void blame_chunk(struct scoreboard *sb,
688 }
689 }
690
691 +struct blame_chunk_cb_data {
692 + struct scoreboard *sb;
693 + struct origin *target;
694 + struct origin *parent;
695 + long plno;
696 + long tlno;
697 +};
698 +
699 +static void blame_chunk_cb(void *data, long same, long p_next, long t_next)
700 +{
701 + struct blame_chunk_cb_data *d = data;
702 + blame_chunk(d->sb, d->tlno, d->plno, same, d->target, d->parent);
703 + d->plno = p_next;
704 + d->tlno = t_next;
705 +}
706 +
707 /*
708 * We are looking at the origin 'target' and aiming to pass blame
709 * for the lines it is suspected to its parent. Run diff to find
@@ -804,36 +713,28 @@ static int pass_blame_to_parent(struct scoreboard *sb,
713 struct origin *target,
714 struct origin *parent)
715 {
807 - int i, last_in_target, plno, tlno;
808 - struct patch *patch;
716 + int last_in_target;
717 mmfile_t file_p, file_o;
718 + struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 };
719 + xpparam_t xpp;
720 + xdemitconf_t xecfg;
721
722 last_in_target = find_last_in_target(sb, target);
723 if (last_in_target < 0)
724 return 1; /* nothing remains for this target */
725
815 - /*
816 - * Run diff between two origins and grab the patch output, so that
817 - * we can pass blame for lines origin is currently suspected for
818 - * to its parent.
819 - */
726 fill_origin_blob(parent, &file_p);
727 fill_origin_blob(target, &file_o);
822 - patch = compare_buffer(&file_p, &file_o, 0);
728 num_get_patch++;
729
825 - plno = tlno = 0;
826 - for (i = 0; i < patch->num; i++) {
827 - struct chunk *chunk = &patch->chunks[i];
828 -
829 - blame_chunk(sb, tlno, plno, chunk->same, target, parent);
830 - plno = chunk->p_next;
831 - tlno = chunk->t_next;
832 - }
730 + memset(&xpp, 0, sizeof(xpp));
731 + xpp.flags = xdl_opts;
732 + memset(&xecfg, 0, sizeof(xecfg));
733 + xecfg.ctxlen = 0;
734 + xdi_diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, &xpp, &xecfg);
735 /* The rest (i.e. anything after tlno) are the same as the parent */
834 - blame_chunk(sb, tlno, plno, last_in_target, target, parent);
736 + blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent);
737
836 - free_patch(patch);
738 return 0;
739 }
740
@@ -925,6 +826,23 @@ static void handle_split(struct scoreboard *sb,
826 }
827 }
828
829 +struct handle_split_cb_data {
830 + struct scoreboard *sb;
831 + struct blame_entry *ent;
832 + struct origin *parent;
833 + struct blame_entry *split;
834 + long plno;
835 + long tlno;
836 +};
837 +
838 +static void handle_split_cb(void *data, long same, long p_next, long t_next)
839 +{
840 + struct handle_split_cb_data *d = data;
841 + handle_split(d->sb, d->ent, d->tlno, d->plno, same, d->parent, d->split);
842 + d->plno = p_next;
843 + d->tlno = t_next;
844 +}
845 +
846 /*
847 * Find the lines from parent that are the same as ent so that
848 * we can pass blames to it. file_p has the blob contents for
@@ -939,8 +857,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
857 const char *cp;
858 int cnt;
859 mmfile_t file_o;
942 - struct patch *patch;
943 - int i, plno, tlno;
860 + struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 };
861 + xpparam_t xpp;
862 + xdemitconf_t xecfg;
863
864 /*
865 * Prepare mmfile that contains only the lines in ent.
@@ -955,24 +874,18 @@ static void find_copy_in_blob(struct scoreboard *sb,
874 }
875 file_o.size = cp - file_o.ptr;
876
958 - patch = compare_buffer(file_p, &file_o, 1);
959 -
877 /*
878 * file_o is a part of final image we are annotating.
879 * file_p partially may match that image.
880 */
881 + memset(&xpp, 0, sizeof(xpp));
882 + xpp.flags = xdl_opts;
883 + memset(&xecfg, 0, sizeof(xecfg));
884 + xecfg.ctxlen = 1;
885 memset(split, 0, sizeof(struct blame_entry [3]));
965 - plno = tlno = 0;
966 - for (i = 0; i < patch->num; i++) {
967 - struct chunk *chunk = &patch->chunks[i];
968 -
969 - handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
970 - plno = chunk->p_next;
971 - tlno = chunk->t_next;
972 - }
886 + xdi_diff_hunks(file_p, &file_o, handle_split_cb, &d, &xpp, &xecfg);
887 /* remainder, if any, all match the preimage */
974 - handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
975 - free_patch(patch);
888 + handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
889 }
890
891 /*