Code

gitk: Implement batch lookup and caching of encoding attrs
authorAlexander Gavrilov <angavrilov@gmail.com>
Mon, 13 Oct 2008 08:12:33 +0000 (12:12 +0400)
committerPaul Mackerras <paulus@samba.org>
Tue, 14 Oct 2008 11:25:54 +0000 (22:25 +1100)
When the diff contains thousands of files, calling git-check-attr once
per file is very slow.  With this patch gitk does attribute lookup in
batches of 30 files while reading the diff file list, which leads to a
very noticeable speedup.

It may be possible to reimplement this even more efficiently, if
git-check-attr is modified to support a --stdin-paths option.
Additionally, it should quote the ':' character in file paths, or
provide a more robust way of column separation.

Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
Tested-by: Johannes Sixt <johannes.sixt@telecom.at>
Signed-off-by: Paul Mackerras <paulus@samba.org>
gitk

diff --git a/gitk b/gitk
index 5f35f612c7dbebb4d9a66d4b8695599fc69f4eee..8cd3171c4c89ea7813d97d5488982a621581e8ba 100755 (executable)
--- a/gitk
+++ b/gitk
@@ -6531,6 +6531,7 @@ proc gettreediffline {gdtf ids} {
     global cmitmode vfilelimit curview limitdiffs
 
     set nr 0
+    set sublist {}
     while {[incr nr] <= 1000 && [gets $gdtf line] >= 0} {
        set i [string first "\t" $line]
        if {$i >= 0} {
@@ -6540,8 +6541,10 @@ proc gettreediffline {gdtf ids} {
            }
            set file [encoding convertfrom $file]
            lappend treediff $file
+           lappend sublist $file
        }
     }
+    cache_gitattr encoding $sublist
     if {![eof $gdtf]} {
        return [expr {$nr >= 1000? 2: 1}]
     }
@@ -9816,18 +9819,48 @@ proc tcl_encoding {enc} {
 }
 
 proc gitattr {path attr default} {
-       if {[catch {set r [exec git check-attr $attr -- $path]}]} {
+       global path_attr_cache
+       if {[info exists path_attr_cache($attr,$path)]} {
+               set r $path_attr_cache($attr,$path)
+       } elseif {[catch {set r [exec git check-attr $attr -- $path]}]} {
                set r unspecified
        } else {
                set r [join [lrange [split $r :] 2 end] :]
                regsub {^ } $r {} r
        }
+       set path_attr_cache($attr,$path) $r
        if {$r eq {unspecified}} {
                return $default
        }
        return $r
 }
 
+proc cache_gitattr {attr pathlist} {
+       global path_attr_cache
+       set newlist {}
+       foreach path $pathlist {
+               if {[info exists path_attr_cache($attr,$path)]} continue
+               lappend newlist $path
+       }
+       while {$newlist ne {}} {
+               set head [lrange $newlist 0 29]
+               set newlist [lrange $newlist 30 end]
+               if {![catch {set rlist [eval exec git check-attr $attr -- $head]}]} {
+                       foreach row [split $rlist "\n"] {
+                               set cols [split $row :]
+                               set path [lindex $cols 0]
+                               set value [join [lrange $cols 2 end] :]
+                               if {[string index $path 0] eq "\""} {
+                                       set path [encoding convertfrom [lindex $path 0]]
+                               }
+                               regsub {^ } $value {} value
+                               set path_attr_cache($attr,$path) $value
+                       }
+               }
+               update
+       }
+}
+
 proc get_path_encoding {path} {
        global gui_encoding
        set tcl_enc [tcl_encoding $gui_encoding]