summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-06-23 10:00:12 +0000
committerZac Medico <zmedico@gentoo.org>2008-06-23 10:00:12 +0000
commit881a3de8afdcfdcb51170eca77acd685cb4021e8 (patch)
treef66d39afcb8442d5fe3d36dea24a1e96dc071a1f
parent0308312e1aab84103bd527ed0beb0e5657ca839e (diff)
downloadportage-881a3de8afdcfdcb51170eca77acd685cb4021e8.tar.gz
portage-881a3de8afdcfdcb51170eca77acd685cb4021e8.tar.bz2
portage-881a3de8afdcfdcb51170eca77acd685cb4021e8.zip
Bug #228977 - During dblink._preserve_libs() calls, cache results of
LinkageMap.findProviders(), LinkageMap.findConsumers(), and os.path.realpath() calls in order to improve performance. This makes a huge difference in performance for glibc upgrades since glibc provides so many libs to check consumerge for. svn path=/main/trunk/; revision=10764
-rw-r--r--pym/portage/dbapi/vartree.py57
1 files changed, 45 insertions, 12 deletions
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index f71a20794..835892722 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -201,30 +201,48 @@ class LinkageMap(object):
def findProviders(self, obj):
if not self._libs:
self.rebuild()
+
+ realpath_cache = {}
+ def realpath(p):
+ real_path = realpath_cache.get(p)
+ if real_path is None:
+ real_path = os.path.realpath(p)
+ realpath_cache[p] = real_path
+ return real_path
+
rValue = {}
if obj not in self._obj_properties:
- obj = os.path.realpath(obj)
+ obj = realpath(obj)
if obj not in self._obj_properties:
raise KeyError("%s not in object list" % obj)
arch, needed, path, soname = self._obj_properties[obj]
path.extend(self._defpath)
- path = [os.path.realpath(x) for x in path]
+ path = set(realpath(x) for x in path)
for x in needed:
rValue[x] = set()
if x not in self._libs or arch not in self._libs[x]:
continue
for y in self._libs[x][arch]["providers"]:
- if x[0] == os.sep and os.path.realpath(x) == os.path.realpath(y):
+ if x[0] == os.sep and realpath(x) == realpath(y):
rValue[x].add(y)
- elif os.path.realpath(os.path.dirname(y)) in path:
+ elif realpath(os.path.dirname(y)) in path:
rValue[x].add(y)
return rValue
def findConsumers(self, obj):
if not self._libs:
self.rebuild()
+
+ realpath_cache = {}
+ def realpath(p):
+ real_path = realpath_cache.get(p)
+ if real_path is None:
+ real_path = os.path.realpath(p)
+ realpath_cache[p] = real_path
+ return real_path
+
if obj not in self._obj_properties:
- obj = os.path.realpath(obj)
+ obj = realpath(obj)
if obj not in self._obj_properties:
raise KeyError("%s not in object list" % obj)
rValue = set()
@@ -233,10 +251,10 @@ class LinkageMap(object):
if obj in self._libs[soname][arch]["providers"]:
for x in self._libs[soname][arch]["consumers"]:
path = self._obj_properties[x][2]
- path = [os.path.realpath(y) for y in path+self._defpath]
- if soname[0] == os.sep and os.path.realpath(soname) == os.path.realpath(obj):
+ path = [realpath(y) for y in path+self._defpath]
+ if soname[0] == os.sep and realpath(soname) == realpath(obj):
rValue.add(x)
- elif os.path.realpath(os.path.dirname(obj)) in path:
+ elif realpath(os.path.dirname(obj)) in path:
rValue.add(x)
return rValue
@@ -1995,9 +2013,15 @@ class dblink(object):
if os.path.islink(x) and os.path.realpath(x) in candidates and x not in mycontents:
candidates.add(x)
+ provider_cache = {}
+ consumer_cache = {}
+
# ignore any libs that are only internally used by the package
def has_external_consumers(lib, contents, otherlibs):
- consumers = linkmap.findConsumers(lib)
+ consumers = consumer_cache.get(lib)
+ if consumers is None:
+ consumers = linkmap.findConsumers(lib)
+ consumer_cache[lib] = consumers
contents_without_libs = [x for x in contents if x not in otherlibs]
# just used by objects that will be autocleaned
@@ -2024,10 +2048,19 @@ class dblink(object):
continue
# only preserve the lib if there is no other copy to use for each consumer
keep = False
- for c in linkmap.findConsumers(lib):
+
+ lib_consumers = consumer_cache.get(lib)
+ if lib_consumers is None:
+ lib_consumers = linkmap.findConsumers(lib)
+ consumer_cache[lib] = lib_consumers
+
+ for c in lib_consumers:
localkeep = True
- providers = linkmap.findProviders(c)
-
+ providers = provider_cache.get(c)
+ if providers is None:
+ providers = linkmap.findProviders(c)
+ provider_cache[c] = providers
+
for soname in providers:
if lib in providers[soname]:
for p in providers[soname]: