From 1c1bfde05a7c1729de8ea72a23f29cd9dfaa1016 Mon Sep 17 00:00:00 2001 From: PJ Eby Date: Thu, 15 Dec 2005 18:10:10 +0000 Subject: Improve startup performance when sys.path contains a lot of eggs, by caching normalized versions of path entries. It appears that normalizing paths using os.path.realpath is extremely expensive on at least Windows. Caching cuts the overhead by around 30X. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041698 --- pkg_resources.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'pkg_resources.py') diff --git a/pkg_resources.py b/pkg_resources.py index ba4cf861..cd67c20b 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -1357,7 +1357,7 @@ register_finder(object,find_nothing) def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" - path_item = normalize_path(path_item) + path_item = _normalize_cached(path_item) if os.path.isdir(path_item): if path_item.lower().endswith('.egg'): @@ -1478,9 +1478,9 @@ def file_ns_handler(importer, path_item, packageName, module): """Compute an ns-package subpath for a filesystem or zipfile importer""" subpath = os.path.join(path_item, packageName.split('.')[-1]) - normalized = normalize_path(subpath) + normalized = _normalize_cached(subpath) for item in module.__path__: - if normalize_path(item)==normalized: + if _normalize_cached(item)==normalized: break else: # Only return the path if it's not already there @@ -1500,6 +1500,12 @@ def normalize_path(filename): """Normalize a file/dir name for comparison purposes""" return os.path.normcase(os.path.realpath(filename)) +def _normalize_cached(filename,_cache={}): + try: + return _cache[filename] + except KeyError: + _cache[filename] = result = normalize_path(filename) + return result def _set_parent_ns(packageName): parts = packageName.split('.') @@ -1509,12 +1515,6 @@ def _set_parent_ns(packageName): setattr(sys.modules[parent], name, sys.modules[packageName]) - - - - - - def yield_lines(strs): """Yield non-empty/non-comment lines of a ``basestring`` or sequence""" if isinstance(strs,basestring): @@ -1876,7 +1876,7 @@ class Distribution(object): #@classmethod def from_filename(cls,filename,metadata=None): return cls.from_location( - normalize_path(filename), os.path.basename(filename), metadata + _normalize_cached(filename), os.path.basename(filename), metadata ) from_filename = classmethod(from_filename) @@ -1915,7 +1915,7 @@ class Distribution(object): self.check_version_conflict() best, pos = 0, -1 for p,item in enumerate(path): - item = normalize_path(item) + item = _normalize_cached(item) if loc.startswith(item) and len(item)>best and loc<>item: best, pos = len(item), p if pos==-1: -- cgit v1.2.1