[kupfer] icons: Use a LRU cache for the icons



commit c0330e13be4d45f4b1bcccceff96360e654dd510
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sat Apr 2 01:50:41 2011 +0200

    icons: Use a LRU cache for the icons
    
    Don't store all icons indefinitely, use a recently-used cache to speed
    up the functions in the kupfer.icon module. Keeping 25 pixbuf of each
    of the small and large size is fast enough.

 kupfer/datatools.py |   28 ++++++++++++++++++++++++++++
 kupfer/icons.py     |   19 ++++++++++++-------
 2 files changed, 40 insertions(+), 7 deletions(-)
---
diff --git a/kupfer/datatools.py b/kupfer/datatools.py
index 2de858b..d020cc4 100644
--- a/kupfer/datatools.py
+++ b/kupfer/datatools.py
@@ -207,6 +207,34 @@ if not OrderedDict:
 		def __ne__(self, other):
 			return not self == other
 
+class LruCache (object):
+	"""
+	Least-recently-used cache mapping of
+	size @maxsiz
+	"""
+	def __init__(self, maxsiz):
+		self.d = OrderedDict()
+		self.maxsiz = maxsiz
+
+	def __contains__(self, key):
+		return key in self.d
+
+	def __setitem__(self, key, value):
+		self.d.pop(key, None)
+		self.d[key] = value
+		if len(self.d) > self.maxsiz:
+			# remove the first item (was inserted longest time ago)
+			lastkey = next(iter(self.d))
+			self.d.pop(lastkey)
+
+	def __getitem__(self, key):
+		try:
+			value = self.d.pop(key)
+		except KeyError:
+			raise
+		# reinsert the value, puts it "last" in the order
+		self.d[key] = value
+		return value
 
 if __name__ == '__main__':
 	import doctest
diff --git a/kupfer/icons.py b/kupfer/icons.py
index 9d20eac..074c7e6 100644
--- a/kupfer/icons.py
+++ b/kupfer/icons.py
@@ -7,10 +7,16 @@ from gio import Icon, ThemedIcon, FileIcon, File
 from gio import FILE_ATTRIBUTE_STANDARD_ICON, FILE_ATTRIBUTE_THUMBNAIL_PATH
 from gobject import GError
 
-from kupfer import config, pretty, scheduler
+from kupfer import config
+from kupfer import datatools
+from kupfer import pretty
+from kupfer import scheduler
 
 icon_cache = {}
 
+# number of elements in icon lru cache (per icon size)
+ICON_CACHE_SIZE = 15
+
 LARGE_SZ = 128
 SMALL_SZ = 24
 
@@ -65,18 +71,17 @@ def get_icon(key, icon_size):
 		rec = icon_cache[icon_size][key]
 	except KeyError:
 		return
-	rec["accesses"] += 1
-	yield rec["icon"]
+	yield rec
 
 def store_icon(key, icon_size, icon):
 	"""
 	Store an icon in cache. It must not have been stored before
 	"""
-	assert key not in icon_cache.get(icon_size, ()), \
-		"icon %s already in cache" % key
 	assert icon, "icon %s may not be %s" % (key, icon)
-	icon_rec = {"icon":icon, "accesses":0}
-	icon_cache.setdefault(icon_size, {})[key] = icon_rec
+	icon_rec = icon
+	if icon_size not in icon_cache:
+		icon_cache[icon_size] = datatools.LruCache(ICON_CACHE_SIZE)
+	icon_cache[icon_size][key] = icon_rec
 
 def _get_icon_dwim(icon, icon_size):
 	"""Make an icon at @icon_size where



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]