Re: gitk: avoid obscene memory consumption
- From
Markus Hitter <mah@jump-ing.de>
- Date
- Nov 7, 2016, 13:43 UTC
- Message-ID
- <3b16a0f5-46e3-b41c-553a-473ad3e9cf26@jump-ing.de>
- In-Reply-To
- <20161107041138.rnlzyuacoezsfwif@oak.ozlabs.ibm.com>
Am 07.11.2016 um 05:11 schrieb Paul Mackerras:
>> - Storing only the actually viewed diff. It's an interactive tool, so there's no advantage in displaying the diff in 0.001 seconds over viewing it in 0.1 seconds. As far as I can see, Gitk currently stores every diff it gets a hold of forever. > It does? That would be a bug. :) >
So far I've found three arrays being populated lazily (which is good) but never being released (which ignores changes to the underlying repo):
$commitinfo: one entry of about 500 bytes per line viewed in the list of commits. Maximum size of the array is the number of commits. As far as I can see, this array should be removed on a reload (Shift-F5).
$blobdifffd: one entry of about 45 bytes for every commit ever read. The underlying file descriptor gets closed, but the entry in this array remains. So far I didn't find the reason why this array exists at all. It's also not removed on a reload.
$treediffs: always the same number of entries as $blobdiffd, but > 1000 bytes/entry. Removed/refreshed on a reload (good!), different number of entries from that point on.
In case you want to play as well, here's the code I wrote for the investigation, it can be appended right at the bottom of the gitk script:
--------------8<---------------
proc variableSizes {} {
# Add variable here to get them shown.
global diffcontext diffids blobdifffd currdiffsubmod commitinfo
global diffnexthead diffnextnote difffilestart
global diffinhdr treediffs puts "---------------------------------------------------"
foreach V [info vars] {
if { ! [info exists $V] } {
continue
} set count 0
set bytes 0
if [array exists $V] {
set count [array size $V]
foreach I [array get $V] {
set bytes [expr $bytes + [string bytelength $I]]
}
} elseif [catch {llength [set $V]}] {
set count [llength [set $V]]
# set bytes [string bytelength [list {*}[set $V]]]
} else {
set bytes [string bytelength [set $V]]
}
puts [format "%20s: %5d items, %10d bytes" $V $count $bytes]
}# catch { # set output [memory info] # puts $output # }
after 3000 variableSizes }
variableSizes -------------->8---------------
[memory info] requires a Tcl with memory debug enabled.
Markus
-- - - - - - - - - - - - - - - - - - - - Dipl. Ing. (FH) Markus Hitter http://www.jump-ing.de/