gitk: Further speedups

Now we don't parse the commits as we are reading them, we just put
commit data on a list as a blob, and instead parse the commit when
we need the various parts of it, such as when a commit is drawn on
the canvas.  This makes searching a bit more interesting: now we
scan through the commit blobs doing a string or regexp match to find
commits that might match, then for those that might match, we parse
the commit info (if it isn't already parsed) and do the matching
for the various fields as before.

Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
Paul Mackerras 2006-03-02 22:56:44 +11:00
parent 8f7d0cecf4
commit 8ed1648415

79
gitk
View File

@ -35,6 +35,7 @@ proc parse_args {rargs} {
proc start_rev_list {rlargs} { proc start_rev_list {rlargs} {
global startmsecs nextupdate ncmupdate global startmsecs nextupdate ncmupdate
global commfd leftover tclencoding datemode global commfd leftover tclencoding datemode
global commitdata
set startmsecs [clock clicks -milliseconds] set startmsecs [clock clicks -milliseconds]
set nextupdate [expr {$startmsecs + 100}] set nextupdate [expr {$startmsecs + 100}]
@ -52,6 +53,7 @@ proc start_rev_list {rlargs} {
exit 1 exit 1
} }
set leftover {} set leftover {}
set commitdata {}
fconfigure $commfd -blocking 0 -translation lf fconfigure $commfd -blocking 0 -translation lf
if {$tclencoding != {}} { if {$tclencoding != {}} {
fconfigure $commfd -encoding $tclencoding fconfigure $commfd -encoding $tclencoding
@ -72,11 +74,9 @@ proc getcommits {rargs} {
} }
proc getcommitlines {commfd} { proc getcommitlines {commfd} {
global parents cdate children nchildren global commitlisted nextupdate
global commitlisted commitinfo phase nextupdate global leftover
global stopped leftover global displayorder commitidx commitrow commitdata
global canv
global displayorder commitidx commitrow
set stuff [read $commfd] set stuff [read $commfd]
if {$stuff == {}} { if {$stuff == {}} {
@ -136,12 +136,9 @@ proc getcommitlines {commfd} {
} }
set id [lindex $ids 0] set id [lindex $ids 0]
set olds [lrange $ids 1 end] set olds [lrange $ids 1 end]
set cmit [string range $cmit [expr {$j + 1}] end]
set commitlisted($id) 1 set commitlisted($id) 1
updatechildren $id [lrange $ids 1 end] updatechildren $id [lrange $ids 1 end]
if {![info exists commitinfo($id)]} { lappend commitdata [string range $cmit [expr {$j + 1}] end]
parsecommit $id $cmit 1
}
set commitrow($id) $commitidx set commitrow($id) $commitidx
incr commitidx incr commitidx
lappend displayorder $id lappend displayorder $id
@ -269,6 +266,25 @@ proc parsecommit {id contents listed} {
$comname $comdate $comment] $comname $comdate $comment]
} }
proc getcommit {id {row {}}} {
global commitdata commitrow commitinfo nparents
if {$row eq {}} {
if {![info exists commitrow($id)]} {return 0}
set row $commitrow($id)
}
if {$row < [llength $commitdata]} {
parsecommit $id [lindex $commitdata $row] 1
} else {
readcommit $id
if {![info exists commitinfo($id)]} {
set commitinfo($id) {"No commit information available"}
set nparents($id) 0
}
}
return 1
}
proc readrefs {} { proc readrefs {} {
global tagids idtags headids idheads tagcontents global tagids idtags headids idheads tagcontents
global otherrefids idotherrefs global otherrefids idotherrefs
@ -1317,6 +1333,7 @@ proc drawcmitrow {row} {
global displayorder rowidlist global displayorder rowidlist
global idrowranges idrangedrawn iddrawn global idrowranges idrangedrawn iddrawn
global commitinfo commitlisted parents numcommits global commitinfo commitlisted parents numcommits
global commitdata
if {$row >= $numcommits} return if {$row >= $numcommits} return
foreach id [lindex $rowidlist $row] { foreach id [lindex $rowidlist $row] {
@ -1344,11 +1361,7 @@ proc drawcmitrow {row} {
return return
} }
if {![info exists commitinfo($id)]} { if {![info exists commitinfo($id)]} {
readcommit $id getcommit $id $row
if {![info exists commitinfo($id)]} {
set commitinfo($id) {"No commit information available"}
set nparents($id) 0
}
} }
assigncolor $id assigncolor $id
if {[info exists commitlisted($id)] && [info exists parents($id)] if {[info exists commitlisted($id)] && [info exists parents($id)]
@ -1604,19 +1617,19 @@ proc xcoord {i level ln} {
} }
proc finishcommits {} { proc finishcommits {} {
global phase global commitidx phase
global canv mainfont ctext maincursor textcursor global canv mainfont ctext maincursor textcursor
if {$phase == "incrdraw"} { if {$commitidx > 0} {
drawrest drawrest
} else { } else {
$canv delete all $canv delete all
$canv create text 3 3 -anchor nw -text "No commits selected" \ $canv create text 3 3 -anchor nw -text "No commits selected" \
-font $mainfont -tags textitems -font $mainfont -tags textitems
set phase {}
} }
. config -cursor $maincursor . config -cursor $maincursor
settextcursor $textcursor settextcursor $textcursor
set phase {}
} }
# Don't change the text pane cursor if it is currently the hand cursor, # Don't change the text pane cursor if it is currently the hand cursor,
@ -1672,7 +1685,8 @@ proc dofind {} {
global findtype findloc findstring markedmatches commitinfo global findtype findloc findstring markedmatches commitinfo
global numcommits displayorder linehtag linentag linedtag global numcommits displayorder linehtag linentag linedtag
global mainfont namefont canv canv2 canv3 selectedline global mainfont namefont canv canv2 canv3 selectedline
global matchinglines foundstring foundstrlen global matchinglines foundstring foundstrlen matchstring
global commitdata
stopfindproc stopfindproc
unmarkmatches unmarkmatches
@ -1689,6 +1703,8 @@ proc dofind {} {
} }
set foundstrlen [string length $findstring] set foundstrlen [string length $findstring]
if {$foundstrlen == 0} return if {$foundstrlen == 0} return
regsub -all {[*?\[\\]} $foundstring {\\&} matchstring
set matchstring "*$matchstring*"
if {$findloc == "Files"} { if {$findloc == "Files"} {
findfiles findfiles
return return
@ -1700,8 +1716,21 @@ proc dofind {} {
} }
set didsel 0 set didsel 0
set fldtypes {Headline Author Date Committer CDate Comment} set fldtypes {Headline Author Date Committer CDate Comment}
for {set l 0} {$l < $numcommits} {incr l} { set l -1
foreach d $commitdata {
incr l
if {$findtype == "Regexp"} {
set doesmatch [regexp $foundstring $d]
} elseif {$findtype == "IgnCase"} {
set doesmatch [string match -nocase $matchstring $d]
} else {
set doesmatch [string match $matchstring $d]
}
if {!$doesmatch} continue
set id [lindex $displayorder $l] set id [lindex $displayorder $l]
if {![info exists commitinfo($id)]} {
getcommit $id $l
}
set info $commitinfo($id) set info $commitinfo($id)
set doesmatch 0 set doesmatch 0
foreach f $info ty $fldtypes { foreach f $info ty $fldtypes {
@ -2069,7 +2098,7 @@ proc findcont {id} {
# mark a commit as matching by putting a yellow background # mark a commit as matching by putting a yellow background
# behind the headline # behind the headline
proc markheadline {l id} { proc markheadline {l id} {
global canv mainfont linehtag commitinfo global canv mainfont linehtag
drawcmitrow $l drawcmitrow $l
set bbox [$canv bbox $linehtag($l)] set bbox [$canv bbox $linehtag($l)]
@ -2725,9 +2754,9 @@ proc gotocommit {} {
set id [string tolower $sha1string] set id [string tolower $sha1string]
if {[regexp {^[0-9a-f]{4,39}$} $id]} { if {[regexp {^[0-9a-f]{4,39}$} $id]} {
set matches {} set matches {}
for {set l 0} {$l < $numcommits} {incr l} { foreach i $displayorder {
if {[string match $id* [lindex $displayorder $l]]} { if {[string match $id* $i]} {
lappend matches [lindex $displayorder $l] lappend matches $i
} }
} }
if {$matches ne {}} { if {$matches ne {}} {
@ -2755,7 +2784,7 @@ proc lineenter {x y id} {
global hoverx hovery hoverid hovertimer global hoverx hovery hoverid hovertimer
global commitinfo canv global commitinfo canv
if {![info exists commitinfo($id)]} return if {![info exists commitinfo($id)] && ![getcommit $id]} return
set hoverx $x set hoverx $x
set hovery $y set hovery $y
set hoverid $id set hoverid $id
@ -2849,6 +2878,7 @@ proc arrowjump {id n y} {
proc lineclick {x y id isnew} { proc lineclick {x y id isnew} {
global ctext commitinfo children cflist canv thickerline global ctext commitinfo children cflist canv thickerline
if {![info exists commitinfo($id)] && ![getcommit $id]} return
unmarkmatches unmarkmatches
unselectline unselectline
normalline normalline
@ -2890,6 +2920,7 @@ proc lineclick {x y id isnew} {
set i 0 set i 0
foreach child $children($id) { foreach child $children($id) {
incr i incr i
if {![info exists commitinfo($child)] && ![getcommit $child]} continue
set info $commitinfo($child) set info $commitinfo($child)
$ctext insert end "\n\t" $ctext insert end "\n\t"
$ctext insert end $child [list link link$i] $ctext insert end $child [list link link$i]