Commit 8044598c authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Optimize find_load_module() from b45914fa ExternalMethod optimization.

This method is used to import ZODB Components when fallback on filesystem is needed
and used when loading Document and Extension Components.

1,000,000 executions:
  * Before:
    timeit("erp5.component.extension.find_load_module(module_name)",
           setup="import erp5.component.extension; module_name='Hoge'")
    59.073
    59.324
  * b45914fa ExternalMethod optimization:
    timeit("__import__('erp5.component.extension.' + module_name, fromlist='*', level=0)",
           setup="module_name='Hoge'")
    1.754
    1.845
  * This commit:
    timeit("import_module('erp5.component.extension.' + module_name)",
           setup="from importlib import import_module; module_name='Hoge'")
    1.346
    1.311
    => Faster because import_module() calls __import__() without fromlist (not
       needed as it returns module from sys.modules after this) and level
       parameters.
    => Introduced in python3 and backported to python2.7. Recommended over
       __import__ in Python documentation for non-internal usage and when
       getting the module itself and not its top-level one.
parent 7aa5fb76
......@@ -39,6 +39,7 @@ from . import aq_method_lock
from types import ModuleType
from zLOG import LOG, BLATHER, WARNING
from Acquisition import aq_base
from importlib import import_module
class ComponentVersionPackage(ModuleType):
"""
......@@ -369,15 +370,15 @@ class ComponentDynamicPackage(ModuleType):
plain import would hide the real error, instead log it...
"""
fullname = self._namespace + '.' + name
loader = self.find_module(fullname)
if loader is not None:
try:
return loader.load_module(fullname)
except ImportError, e:
import traceback
try:
# Wrapper around __import__ much faster than calling find_module() then
# load_module(), and returning module 'name' in contrary to __import__
# returning 'erp5' (requiring fromlist parameter which is slower)
return import_module(fullname)
except ImportError as e:
if str(e) != "No module named " + name:
LOG("ERP5Type.dynamic", WARNING,
"Could not load Component module '%s'\n%s" % (fullname,
traceback.format_exc()))
"Could not load Component module %r" % fullname, error=True)
return None
......
......@@ -52,22 +52,10 @@ class _(PatchClass(ExternalMethod)):
return self._getFunction(reload)[0]
def _getFunction(self, reload=False):
try:
component_module = __import__(
'erp5.component.extension.' + self._module,
fromlist="*", level=0)
except ImportError, e:
if str(e) != "No module named " + self._module:
# Fall back loudly if a component exists but is broken.
# XXX: We used __import__ instead of
# erp5.component.extension.find_load_module
# because the latter is much slower.
# XXX: Should we also fall back on FS if the module imports
# successfully but does not contain the wanted function?
LOG("ERP5Type.dynamic", WARNING,
"Could not load Component module %r"
% ('erp5.component.extension.' + self._module),
error=1)
import erp5.component.extension
component_module = erp5.component.extension.find_load_module(self._module)
if component_module is None:
# Fall back on filesystem
if not reload:
from Globals import DevelopmentMode
if DevelopmentMode:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment