• Junio C Hamano's avatar
    Optimize "diff-index --cached" using cache-tree · b65982b6
    Junio C Hamano authored
    When running "diff-index --cached" after making a change to only a small
    portion of the index, there is no point unpacking unchanged subtrees into
    the index recursively, only to find that all entries match anyway.  Tweak
    unpack_trees() logic that is used to read in the tree object to catch the
    case where the tree entry we are looking at matches the index as a whole
    by looking at the cache-tree.
    
    As an exercise, after modifying a few paths in the kernel tree, here are
    a few numbers on my Athlon 64X2 3800+:
    
        (without patch, hot cache)
        $ /usr/bin/time git diff --cached --raw
        :100644 100644 b57e1f5... e69de29... M  Makefile
        :100644 000000 8c86b72... 0000000... D  arch/x86/Makefile
        :000000 100644 0000000... e69de29... A  arche
        0.07user 0.02system 0:00.09elapsed 102%CPU (0avgtext+0avgdata 0maxresident)k
        0inputs+0outputs (0major+9407minor)pagefaults 0swaps
    
        (with patch, hot cache)
        $ /usr/bin/time ../git.git/git-diff --cached --raw
        :100644 100644 b57e1f5... e69de29... M  Makefile
        :100644 000000 8c86b72... 0000000... D  arch/x86/Makefile
        :000000 100644 0000000... e69de29... A  arche
        0.02user 0.00system 0:00.02elapsed 103%CPU (0avgtext+0avgdata 0maxresident)k
        0inputs+0outputs (0major+2446minor)pagefaults 0swaps
    
    Cold cache numbers are very impressive, but it does not matter very much
    in practice:
    
        (without patch, cold cache)
        $ su root sh -c 'echo 3 >/proc/sys/vm/drop_caches'
        $ /usr/bin/time git diff --cached --raw
        :100644 100644 b57e1f5... e69de29... M  Makefile
        :100644 000000 8c86b72... 0000000... D  arch/x86/Makefile
        :000000 100644 0000000... e69de29... A  arche
        0.06user 0.17system 0:10.26elapsed 2%CPU (0avgtext+0avgdata 0maxresident)k
        247032inputs+0outputs (1172major+8237minor)pagefaults 0swaps
    
        (with patch, cold cache)
        $ su root sh -c 'echo 3 >/proc/sys/vm/drop_caches'
        $ /usr/bin/time ../git.git/git-diff --cached --raw
        :100644 100644 b57e1f5... e69de29... M  Makefile
        :100644 000000 8c86b72... 0000000... D  arch/x86/Makefile
        :000000 100644 0000000... e69de29... A  arche
        0.02user 0.01system 0:01.01elapsed 3%CPU (0avgtext+0avgdata 0maxresident)k
        18440inputs+0outputs (79major+2369minor)pagefaults 0swaps
    
    This of course helps "git status" as well.
    
        (without patch, hot cache)
        $ /usr/bin/time ../git.git/git-status >/dev/null
        0.17user 0.18system 0:00.35elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
        0inputs+5336outputs (0major+10970minor)pagefaults 0swaps
    
        (with patch, hot cache)
        $ /usr/bin/time ../git.git/git-status >/dev/null
        0.10user 0.16system 0:00.27elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
        0inputs+5336outputs (0major+3921minor)pagefaults 0swaps
    Signed-off-by: default avatarJunio C Hamano <gitster@pobox.com>
    b65982b6
cache-tree.h 1.36 KB