gitk: Implement batch lookup and caching of encoding attrs
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>
This commit is contained in:
		
				
					committed by
					
						
						Paul Mackerras
					
				
			
			
				
	
			
			
			
						parent
						
							09c7029dfa
						
					
				
				
					commit
					4db09304f9
				
			
							
								
								
									
										35
									
								
								gitk
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								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]
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user