Richard Suchenwirth 2004-11-17 - When time-consuming operations occur more than once on the same input (and giving the same result), it is faster to cache such results for future use in an array keyed with the input (see Result caching). However, if a long-running process uses a cache, it will grow unbounded - less politely expressed, a kind of "leak". So here's a caching code that keeps a list of least-recently-used (LRU) elements (in the "" key - think minimal... assuming that "" is not a valid data key), and deletes the least recently used one once the maximum size is reached:
proc cached {arrName key args} { upvar #0 $arrName arr if {![info exists arr($key)]} { set arr($key) [eval $args] if {[llength $arr()]>=$arr(maxSize)} { unset arr([lindex $arr() 0]) set arr() [lrange $arr() 1 end] } } else { set pos [lsearch $arr() $key] set arr() [lreplace $arr() $pos $pos] } lappend arr() $key ;# LRU list set arr($key) }
Testing: initialize a cache, fill with some data
% array set Cache {maxSize 4 {} {}} % cached Cache a clock seconds 1100702390 % cached Cache b clock seconds 1100702440 % cached Cache c clock seconds 1100702443 % cached Cache d clock seconds 1100702445 % parray Cache Cache() = a b c d Cache(a) = 1100702390 Cache(b) = 1100702440 Cache(c) = 1100702443 Cache(d) = 1100702445 Cache(maxSize) = 4
Ask for the element "a" again (moves it to end of LRU list):
% cached Cache a clock seconds 1100702390 % parray Cache Cache() = b c d a Cache(a) = 1100702390 Cache(b) = 1100702440 Cache(c) = 1100702443 Cache(d) = 1100702445 Cache(maxSize) = 4 % cached Cache c clock seconds 1100702443 % parray Cache Cache() = b d a c Cache(a) = 1100702390 Cache(b) = 1100702440 Cache(c) = 1100702443 Cache(d) = 1100702445 Cache(maxSize) = 4
As maxSize is reached, the least-recently-used "b" will be decached:
% cached Cache x clock seconds 1100704105 % parray Cache Cache() = d a c x Cache(a) = 1100702390 Cache(c) = 1100702443 Cache(d) = 1100702445 Cache(maxSize) = 4 Cache(x) = 1100704105
TV (17 Nov 04) The cache of the processor chip involved in these test is hard to put in the same beginning state to actually test these kinds of scenarios. Maybe except starting the the machine up again in the same sequence.