git-gui: More performance improvements to rescan logic.
Removed as much as possible from the merge_state proc, which is where we spent most of our time before UI update. This change makes our running time match that of git status, except that we then need about 7 additional seconds to draw 6900 files on screen. Apparently the [array names a -exact $v] operator in Tcl is O(n) rather than O(1), which is really quite disappointing given that each array can only have one entry for a given value. Switching to a lookup with a catch (whose error we ignore) runs in O(1) time and bought us most of that improvement. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
parent
93f654df7e
commit
6b29267542
87
git-gui
87
git-gui
@ -70,7 +70,7 @@ proc repository_state {hdvar ctvar} {
|
|||||||
proc update_status {{final Ready.}} {
|
proc update_status {{final Ready.}} {
|
||||||
global HEAD PARENT commit_type
|
global HEAD PARENT commit_type
|
||||||
global ui_index ui_other ui_status_value ui_comm
|
global ui_index ui_other ui_status_value ui_comm
|
||||||
global status_active file_states
|
global status_active file_states status_start
|
||||||
|
|
||||||
if {$status_active || ![lock_index read]} return
|
if {$status_active || ![lock_index read]} return
|
||||||
|
|
||||||
@ -84,6 +84,7 @@ proc update_status {{final Ready.}} {
|
|||||||
set commit_type $new_type
|
set commit_type $new_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set status_start [clock seconds]
|
||||||
array unset file_states
|
array unset file_states
|
||||||
foreach w [list $ui_index $ui_other] {
|
foreach w [list $ui_index $ui_other] {
|
||||||
$w conf -state normal
|
$w conf -state normal
|
||||||
@ -230,7 +231,7 @@ proc read_ls_others {fd final} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc status_eof {fd buf final} {
|
proc status_eof {fd buf final} {
|
||||||
global status_active $buf
|
global status_active status_start $buf
|
||||||
global ui_fname_value ui_status_value file_states
|
global ui_fname_value ui_status_value file_states
|
||||||
|
|
||||||
if {[eof $fd]} {
|
if {[eof $fd]} {
|
||||||
@ -240,8 +241,12 @@ proc status_eof {fd buf final} {
|
|||||||
if {[incr status_active -1] == 0} {
|
if {[incr status_active -1] == 0} {
|
||||||
unlock_index
|
unlock_index
|
||||||
|
|
||||||
set ui_status_value $final
|
set e1 [clock seconds]
|
||||||
display_all_files
|
display_all_files
|
||||||
|
set e2 [clock seconds]
|
||||||
|
puts "TIME [expr $e1 - $status_start] + [expr $e2 - $e1] = [expr $e2 - $status_start]"
|
||||||
|
|
||||||
|
set ui_status_value $final
|
||||||
|
|
||||||
if {$ui_fname_value != {} && [array names file_states \
|
if {$ui_fname_value != {} && [array names file_states \
|
||||||
-exact $ui_fname_value] != {}} {
|
-exact $ui_fname_value] != {}} {
|
||||||
@ -664,11 +669,11 @@ proc push_to {remote} {
|
|||||||
## ui helpers
|
## ui helpers
|
||||||
|
|
||||||
proc mapcol {state path} {
|
proc mapcol {state path} {
|
||||||
global all_cols
|
global all_cols ui_other
|
||||||
|
|
||||||
if {[catch {set r $all_cols($state)}]} {
|
if {[catch {set r $all_cols($state)}]} {
|
||||||
puts "error: no column for state={$state} $path"
|
puts "error: no column for state={$state} $path"
|
||||||
return o
|
return $ui_other
|
||||||
}
|
}
|
||||||
return $r
|
return $r
|
||||||
}
|
}
|
||||||
@ -716,31 +721,34 @@ proc bsearch {w path} {
|
|||||||
|
|
||||||
set next_icon_id 0
|
set next_icon_id 0
|
||||||
|
|
||||||
proc merge_state {path state} {
|
proc merge_state {path new_state} {
|
||||||
global file_states next_icon_id
|
global file_states next_icon_id
|
||||||
|
|
||||||
if {[array names file_states -exact $path] == {}} {
|
set s0 [string index $new_state 0]
|
||||||
set m __
|
set s1 [string index $new_state 1]
|
||||||
set s [list $m icon[incr next_icon_id]]
|
|
||||||
|
if {[catch {set info $file_states($path)}]} {
|
||||||
|
set state __
|
||||||
|
set icon n[incr next_icon_id]
|
||||||
} else {
|
} else {
|
||||||
set s $file_states($path)
|
set state [lindex $info 0]
|
||||||
set m [lindex $s 0]
|
set icon [lindex $info 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[string index $state 0] == {_}} {
|
if {$s0 == {_}} {
|
||||||
set state [string index $m 0][string index $state 1]
|
set s0 [string index $state 0]
|
||||||
} elseif {[string index $state 0] == {*}} {
|
} elseif {$s0 == {*}} {
|
||||||
set state _[string index $state 1]
|
set s0 _
|
||||||
}
|
}
|
||||||
|
|
||||||
if {[string index $state 1] == {_}} {
|
if {$s1 == {_}} {
|
||||||
set state [string index $state 0][string index $m 1]
|
set s1 [string index $state 1]
|
||||||
} elseif {[string index $state 1] == {*}} {
|
} elseif {$s1 == {*}} {
|
||||||
set state [string index $state 0]_
|
set s1 _
|
||||||
}
|
}
|
||||||
|
|
||||||
set file_states($path) [lreplace $s 0 0 $state]
|
set file_states($path) [list $s0$s1 $icon]
|
||||||
return $m
|
return $state
|
||||||
}
|
}
|
||||||
|
|
||||||
proc display_file {path state} {
|
proc display_file {path state} {
|
||||||
@ -750,19 +758,12 @@ proc display_file {path state} {
|
|||||||
if {$status_active} return
|
if {$status_active} return
|
||||||
|
|
||||||
set s $file_states($path)
|
set s $file_states($path)
|
||||||
|
set old_w [mapcol $old_m $path]
|
||||||
|
set new_w [mapcol $new_m $path]
|
||||||
set new_m [lindex $s 0]
|
set new_m [lindex $s 0]
|
||||||
set new_col [mapcol $new_m $path]
|
|
||||||
set new_ico [mapicon $new_m $path]
|
set new_ico [mapicon $new_m $path]
|
||||||
|
|
||||||
if {$new_col == {o}} {
|
if {$new_w != $old_w} {
|
||||||
set old_w $ui_index
|
|
||||||
set new_w $ui_other
|
|
||||||
} else {
|
|
||||||
set old_w $ui_other
|
|
||||||
set new_w $ui_index
|
|
||||||
}
|
|
||||||
|
|
||||||
if {$new_col != [mapcol $old_m $path]} {
|
|
||||||
set lno [bsearch $old_w $path]
|
set lno [bsearch $old_w $path]
|
||||||
if {$lno >= 0} {
|
if {$lno >= 0} {
|
||||||
incr lno
|
incr lno
|
||||||
@ -795,18 +796,12 @@ proc display_all_files {} {
|
|||||||
foreach path [lsort [array names file_states]] {
|
foreach path [lsort [array names file_states]] {
|
||||||
set s $file_states($path)
|
set s $file_states($path)
|
||||||
set m [lindex $s 0]
|
set m [lindex $s 0]
|
||||||
|
set w [mapcol $m $path]
|
||||||
if {[mapcol $m $path] == {o}} {
|
$w image create end \
|
||||||
set aw $ui_other
|
|
||||||
} else {
|
|
||||||
set aw $ui_index
|
|
||||||
}
|
|
||||||
|
|
||||||
$aw image create end \
|
|
||||||
-align center -padx 5 -pady 1 \
|
-align center -padx 5 -pady 1 \
|
||||||
-name [lindex $s 1] \
|
-name [lindex $s 1] \
|
||||||
-image [mapicon $m $path]
|
-image [mapicon $m $path]
|
||||||
$aw insert end "$path\n"
|
$w insert end "$path\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
$ui_index conf -state disabled
|
$ui_index conf -state disabled
|
||||||
@ -1025,6 +1020,8 @@ static unsigned char file_merge_bits[] = {
|
|||||||
0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
|
0xfa, 0x17, 0x02, 0x10, 0xfe, 0x1f};
|
||||||
} -maskdata $filemask
|
} -maskdata $filemask
|
||||||
|
|
||||||
|
set ui_index .vpane.files.index.list
|
||||||
|
set ui_other .vpane.files.other.list
|
||||||
set max_status_desc 0
|
set max_status_desc 0
|
||||||
foreach i {
|
foreach i {
|
||||||
{__ i plain "Unmodified"}
|
{__ i plain "Unmodified"}
|
||||||
@ -1035,7 +1032,7 @@ foreach i {
|
|||||||
{_O o plain "Untracked"}
|
{_O o plain "Untracked"}
|
||||||
{A_ o fulltick "Added"}
|
{A_ o fulltick "Added"}
|
||||||
{AM o parttick "Partially added"}
|
{AM o parttick "Partially added"}
|
||||||
{AD o question "Added (but now gone)"}
|
{AD o question "Added (but now gone)"}
|
||||||
|
|
||||||
{_D i question "Missing"}
|
{_D i question "Missing"}
|
||||||
{D_ i removed "Removed"}
|
{D_ i removed "Removed"}
|
||||||
@ -1048,7 +1045,11 @@ foreach i {
|
|||||||
if {$max_status_desc < [string length [lindex $i 3]]} {
|
if {$max_status_desc < [string length [lindex $i 3]]} {
|
||||||
set max_status_desc [string length [lindex $i 3]]
|
set max_status_desc [string length [lindex $i 3]]
|
||||||
}
|
}
|
||||||
set all_cols([lindex $i 0]) [lindex $i 1]
|
if {[lindex $i 1] == {i}} {
|
||||||
|
set all_cols([lindex $i 0]) $ui_index
|
||||||
|
} else {
|
||||||
|
set all_cols([lindex $i 0]) $ui_other
|
||||||
|
}
|
||||||
set all_icons([lindex $i 0]) file_[lindex $i 2]
|
set all_icons([lindex $i 0]) file_[lindex $i 2]
|
||||||
set all_descs([lindex $i 0]) [lindex $i 3]
|
set all_descs([lindex $i 0]) [lindex $i 3]
|
||||||
}
|
}
|
||||||
@ -1461,7 +1462,6 @@ panedwindow .vpane.files -orient horizontal
|
|||||||
pack .vpane -anchor n -side top -fill both -expand 1
|
pack .vpane -anchor n -side top -fill both -expand 1
|
||||||
|
|
||||||
# -- Index File List
|
# -- Index File List
|
||||||
set ui_index .vpane.files.index.list
|
|
||||||
frame .vpane.files.index -height 100 -width 400
|
frame .vpane.files.index -height 100 -width 400
|
||||||
label .vpane.files.index.title -text {Modified Files} \
|
label .vpane.files.index.title -text {Modified Files} \
|
||||||
-background green \
|
-background green \
|
||||||
@ -1479,7 +1479,6 @@ pack $ui_index -side left -fill both -expand 1
|
|||||||
.vpane.files add .vpane.files.index -sticky nsew
|
.vpane.files add .vpane.files.index -sticky nsew
|
||||||
|
|
||||||
# -- Other (Add) File List
|
# -- Other (Add) File List
|
||||||
set ui_other .vpane.files.other.list
|
|
||||||
frame .vpane.files.other -height 100 -width 100
|
frame .vpane.files.other -height 100 -width 100
|
||||||
label .vpane.files.other.title -text {Untracked Files} \
|
label .vpane.files.other.title -text {Untracked Files} \
|
||||||
-background red \
|
-background red \
|
||||||
|
Loading…
Reference in New Issue
Block a user