summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2009-04-15 14:16:28 +0200
committerJulian Andres Klode <jak@debian.org>2009-04-15 14:16:28 +0200
commit2b867aebe32d59b7450f3a7fb22390e0dd9f8cc7 (patch)
tree49d4d5ec7e109dfe55d51ffd2061c96ec18bd5da
parent3caa05aa8e295d338be4bfbe7fdd2e825a59d947 (diff)
downloadpython-apt-2b867aebe32d59b7450f3a7fb22390e0dd9f8cc7.tar.gz
* apt/cache.py: Use set() and WeakValueDictionary() for holding packages.
Only create Package objects when they are requested, do not keep them in a dict. Saves 10MB for 25,000 packages on my machine. The set holds the names of all packages which have at least one version, and the WeakValueDictionary() holds weak references to created Package objects. This way accessing the same package two times should return the same object, kept by the WeakValueDictionary().
-rw-r--r--apt/cache.py38
-rw-r--r--debian/changelog4
2 files changed, 26 insertions, 16 deletions
diff --git a/apt/cache.py b/apt/cache.py
index cc425ccb..d13010af 100644
--- a/apt/cache.py
+++ b/apt/cache.py
@@ -20,6 +20,7 @@
# USA
import os
+import weakref
import apt_pkg
from apt import Package
@@ -80,7 +81,8 @@ class Cache(object):
self._records = apt_pkg.GetPkgRecords(self._cache)
self._list = apt_pkg.GetPkgSourceList()
self._list.ReadMainList()
- self._dict = {}
+ self._set = set()
+ self._weakref = weakref.WeakValueDictionary()
progress.Op = "Building data structures"
i=last=0
@@ -91,7 +93,7 @@ class Cache(object):
last=i
# drop stuff with no versions (cruft)
if len(pkg.VersionList) > 0:
- self._dict[pkg.Name] = Package(self, pkg)
+ self._set.add(pkg.Name)
i += 1
@@ -100,30 +102,36 @@ class Cache(object):
def __getitem__(self, key):
""" look like a dictionary (get key) """
- return self._dict[key]
+ try:
+ return self._weakref[key]
+ except KeyError:
+ if key in self._set:
+ pkg = self._weakref[key] = Package(self, self._cache[key])
+ return pkg
+ else:
+ raise KeyError('The cache has no package named %r' % key)
def __iter__(self):
- for pkgname in self._dict.keys():
- yield self._dict[pkgname]
+ for pkgname in self._set:
+ yield self[pkgname]
raise StopIteration
def has_key(self, key):
- return (key in self._dict)
+ return (key in self._set)
def __contains__(self, key):
- return (key in self._dict)
+ return (key in self._set)
def __len__(self):
- return len(self._dict)
+ return len(self._set)
def keys(self):
- return self._dict.keys()
+ return list(self._set)
def getChanges(self):
""" Get the marked changes """
changes = []
- for name in self._dict.keys():
- p = self._dict[name]
+ for p in self:
if p.markedUpgrade or p.markedInstall or p.markedDelete or \
p.markedDowngrade or p.markedReinstall:
changes.append(p)
@@ -348,7 +356,7 @@ class FilteredCache(object):
return len(self._filtered)
def __getitem__(self, key):
- return self.cache._dict[key]
+ return self.cache[key]
def __iter__(self):
for pkgname in self._filtered:
@@ -366,10 +374,10 @@ class FilteredCache(object):
def _reapplyFilter(self):
" internal helper to refilter "
self._filtered = {}
- for pkg in self.cache._dict.keys():
+ for pkg in self.cache:
for f in self._filters:
- if f.apply(self.cache._dict[pkg]):
- self._filtered[pkg] = 1
+ if f.apply(pkg):
+ self._filtered[pkg.name] = 1
break
def setFilter(self, filter):
diff --git a/debian/changelog b/debian/changelog
index 261ff7bd..6cbdaac7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -5,8 +5,10 @@ python-apt (0.7.11) UNRELEASED; urgency=low
* Replace support for file objects with a more generic support for any object
providing a fileno() method and for file descriptors (integers).
* Add support for the Breaks fields
+ * Only create Package objects when they are requested, do not keep them in
+ a dict. Saves 10MB for 25,000 packages on my machine.
- -- Julian Andres Klode <jak@debian.org> Mon, 13 Apr 2009 18:08:10 +0200
+ -- Julian Andres Klode <jak@debian.org> Wed, 15 Apr 2009 13:47:42 +0200
python-apt (0.7.10.3) unstable; urgency=low