gitk: Speed up resolution of short SHA1 ids

On large repositories such as the Linux kernel, it can take quite a noticeable time (several seconds) for gitk to resolve short SHA1 IDs to their long form. This speeds up the process by maintaining lists of IDs indexed by the first 4 characters of the SHA1 ID, speeding up the search by a factor of 65536 on large repositories. Signed-off-by: Paul Mackerras <paulus@samba.org>

Paul Mackerras committed Mar 19, 2012 at 11:21 UTC 22387f2395217beaa7228cb02966cf7b61b0c346
1 file changed +27 -5
gitk
+27 -5
@@ -641,12 +641,16 @@ proc varcinit {view} {
641
642 proc resetvarcs {view} {
643 global varcid varccommits parents children vseedcount ordertok
644 + global vshortids
645
646 foreach vid [array names varcid $view,*] {
647 unset varcid($vid)
648 unset children($vid)
649 unset parents($vid)
650 }
651 + foreach vid [array names vshortids $view,*] {
652 + unset vshortids($vid)
653 + }
654 # some commits might have children but haven't been seen yet
655 foreach vid [array names children $view,*] {
656 unset children($vid)
@@ -933,7 +937,7 @@ proc fix_reversal {p a v} {
937 proc insertrow {id p v} {
938 global cmitlisted children parents varcid varctok vtokmod
939 global varccommits ordertok commitidx numcommits curview
936 - global targetid targetrow
940 + global targetid targetrow vshortids
941
942 readcommit $id
943 set vid $v,$id
@@ -942,6 +946,7 @@ proc insertrow {id p v} {
946 set parents($vid) [list $p]
947 set a [newvarc $v $id]
948 set varcid($vid) $a
949 + lappend vshortids($v,[string range $id 0 3]) $id
950 if {[string compare [lindex $varctok($v) $a] $vtokmod($v)] < 0} {
951 modify_arc $v $a
952 }
@@ -1397,7 +1402,7 @@ proc getcommitlines {fd inst view updating} {
1402 global commitidx commitdata vdatemode
1403 global parents children curview hlview
1404 global idpending ordertok
1400 - global varccommits varcid varctok vtokmod vfilelimit
1405 + global varccommits varcid varctok vtokmod vfilelimit vshortids
1406
1407 set stuff [read $fd 500000]
1408 # git log doesn't terminate the last commit with a null...
@@ -1497,6 +1502,8 @@ proc getcommitlines {fd inst view updating} {
1502 set id [lindex $ids 0]
1503 set vid $view,$id
1504
1505 + lappend vshortids($view,[string range $id 0 3]) $id
1506 +
1507 if {!$listed && $updating && ![info exists varcid($vid)] &&
1508 $vfilelimit($view) ne {}} {
1509 # git log doesn't rewrite parents for unlisted commits
@@ -1719,11 +1726,26 @@ proc getcommit {id} {
1726 # and are present in the current view.
1727 # This is fairly slow...
1728 proc longid {prefix} {
1722 - global varcid curview
1729 + global varcid curview vshortids
1730
1731 set ids {}
1725 - foreach match [array names varcid "$curview,$prefix*"] {
1726 - lappend ids [lindex [split $match ","] 1]
1732 + if {[string length $prefix] >= 4} {
1733 + set vshortid $curview,[string range $prefix 0 3]
1734 + if {[info exists vshortids($vshortid)]} {
1735 + foreach id $vshortids($vshortid) {
1736 + if {[string match "$prefix*" $id]} {
1737 + if {[lsearch -exact $ids $id] < 0} {
1738 + lappend ids $id
1739 + if {[llength $ids] >= 2} break
1740 + }
1741 + }
1742 + }
1743 + }
1744 + } else {
1745 + foreach match [array names varcid "$curview,$prefix*"] {
1746 + lappend ids [lindex [split $match ","] 1]
1747 + if {[llength $ids] >= 2} break
1748 + }
1749 }
1750 return $ids
1751 }