##// END OF EJS Templates
util: optimize cost auditing on insert...
util: optimize cost auditing on insert Calling popoldest() on insert with cost auditing enabled introduces significant overhead. The primary reason for this overhead is that popoldest() needs to walk the linked list to find the first non-empty node. When we call popoldest() within a loop, this can become quadratic. The performance impact is more pronounced on caches with large capacities. This commit effectively inlines the popoldest() call into _enforcecostlimit(). By doing so, we only do the backwards walk to find the first empty node once. However, we still may still perform this work on insert when the cache is near cost capacity. So this is only a partial performance win. $ hg perflrucachedict --size 4 --gets 1000000 --sets 1000000 --mixed 1000000 --costlimit 100 ! gets w/ cost limit ! wall 0.598737 comb 0.590000 user 0.590000 sys 0.000000 (best of 17) ! inserts w/ cost limit ! wall 1.694282 comb 1.700000 user 1.700000 sys 0.000000 (best of 6) ! wall 1.659181 comb 1.650000 user 1.650000 sys 0.000000 (best of 7) ! mixed w/ cost limit ! wall 1.157655 comb 1.150000 user 1.150000 sys 0.000000 (best of 9) ! wall 1.139955 comb 1.140000 user 1.140000 sys 0.000000 (best of 9) $ hg perflrucachedict --size 1000 --gets 1000000 --sets 1000000 --mixed 1000000 --costlimit 10000 ! gets w/ cost limit ! wall 0.598526 comb 0.600000 user 0.600000 sys 0.000000 (best of 17) ! wall 0.601993 comb 0.600000 user 0.600000 sys 0.000000 (best of 17) ! inserts w/ cost limit ! wall 37.838315 comb 37.840000 user 37.840000 sys 0.000000 (best of 3) ! wall 25.105273 comb 25.080000 user 25.080000 sys 0.000000 (best of 3) ! mixed w/ cost limit ! wall 18.060198 comb 18.060000 user 18.060000 sys 0.000000 (best of 3) ! wall 12.104470 comb 12.070000 user 12.070000 sys 0.000000 (best of 3) $ hg perflrucachedict --size 1000 --gets 1000000 --sets 1000000 --mixed 1000000 --costlimit 10000 --mixedgetfreq 90 ! gets w/ cost limit ! wall 0.600024 comb 0.600000 user 0.600000 sys 0.000000 (best of 17) ! wall 0.614439 comb 0.620000 user 0.620000 sys 0.000000 (best of 17) ! inserts w/ cost limit ! wall 37.154547 comb 37.120000 user 37.120000 sys 0.000000 (best of 3) ! wall 25.963028 comb 25.960000 user 25.960000 sys 0.000000 (best of 3) ! mixed w/ cost limit ! wall 4.381602 comb 4.380000 user 4.370000 sys 0.010000 (best of 3) ! wall 3.174256 comb 3.170000 user 3.170000 sys 0.000000 (best of 4) Differential Revision: https://phab.mercurial-scm.org/D4504

File last commit:

r39488:481db51c merge default
r39605:cc23c09b default
Show More
policy.py
109 lines | 3.6 KiB | text/x-python | PythonLexer
timeless
debuginstall: expose modulepolicy...
r29266 # policy.py - module policy logic for Mercurial.
#
# Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import os
import sys
# Rules for how modules can be loaded. Values are:
#
# c - require C extensions
# allow - allow pure Python implementation when C loading fails
Maciej Fijalkowski
policy: add cffi policy for PyPy...
r29490 # cffi - required cffi versions (implemented within pure module)
# cffi-allow - allow pure Python implementation if cffi version is missing
timeless
debuginstall: expose modulepolicy...
r29266 # py - only load pure Python modules
#
Yuya Nishihara
policy: relax the default for in-place build...
r32251 # By default, fall back to the pure modules so the in-place build can
# run without recompiling the C extensions. This will be overridden by
# __modulepolicy__ generated by setup.py.
policy = b'allow'
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 _packageprefs = {
# policy: (versioned package, pure package)
b'c': (r'cext', None),
b'allow': (r'cext', r'pure'),
Yuya Nishihara
cffi: split modules from pure...
r32512 b'cffi': (r'cffi', None),
b'cffi-allow': (r'cffi', r'pure'),
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 b'py': (None, r'pure'),
}
Maciej Fijalkowski
policy: add cffi policy for PyPy...
r29490
timeless
debuginstall: expose modulepolicy...
r29266 try:
from . import __modulepolicy__
policy = __modulepolicy__.modulepolicy
except ImportError:
pass
# PyPy doesn't load C extensions.
#
# The canonical way to do this is to test platform.python_implementation().
# But we don't import platform and don't bloat for it here.
Yuya Nishihara
policy: mark all string literals as sysstr or bytes...
r32205 if r'__pypy__' in sys.builtin_module_names:
policy = b'cffi'
timeless
debuginstall: expose modulepolicy...
r29266
# Environment variable can always force settings.
FUJIWARA Katsunori
py3: add "b" prefix to string literals related to module policy...
r31361 if sys.version_info[0] >= 3:
Yuya Nishihara
policy: mark all string literals as sysstr or bytes...
r32205 if r'HGMODULEPOLICY' in os.environ:
policy = os.environ[r'HGMODULEPOLICY'].encode(r'utf-8')
FUJIWARA Katsunori
py3: add "b" prefix to string literals related to module policy...
r31361 else:
Yuya Nishihara
policy: mark all string literals as sysstr or bytes...
r32205 policy = os.environ.get(r'HGMODULEPOLICY', policy)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366
def _importfrom(pkgname, modname):
# from .<pkgname> import <modname> (where . is looked through this module)
fakelocals = {}
pkg = __import__(pkgname, globals(), fakelocals, [modname], level=1)
try:
fakelocals[modname] = mod = getattr(pkg, modname)
except AttributeError:
raise ImportError(r'cannot import name %s' % modname)
# force import; fakelocals[modname] may be replaced with the real module
getattr(mod, r'__doc__', None)
return fakelocals[modname]
Jun Wu
policy: define C module versions individually...
r32428 # keep in sync with "version" in C modules
_cextversions = {
Yuya Nishihara
policy: extend API version checks for cffi...
r32511 (r'cext', r'base85'): 1,
Jun Wu
bdiff: add a xdiffblocks method...
r36693 (r'cext', r'bdiff'): 3,
Yuya Nishihara
policy: extend API version checks for cffi...
r32511 (r'cext', r'mpatch'): 1,
Augie Fackler
osutil: implement minimal __getitem__ compatibility on our custom listdir type...
r36798 (r'cext', r'osutil'): 4,
Gregory Szorc
merge with stable...
r39488 (r'cext', r'parsers'): 11,
Jun Wu
policy: define C module versions individually...
r32428 }
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 # map import request to other package or module
_modredirects = {
Yuya Nishihara
encoding: drop circular import by proxying through '<policy>.charencode'...
r33756 (r'cext', r'charencode'): (r'cext', r'parsers'),
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 (r'cffi', r'base85'): (r'pure', r'base85'),
Yuya Nishihara
encoding: drop circular import by proxying through '<policy>.charencode'...
r33756 (r'cffi', r'charencode'): (r'pure', r'charencode'),
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 (r'cffi', r'parsers'): (r'pure', r'parsers'),
}
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 def _checkmod(pkgname, modname, mod):
Yuya Nishihara
policy: extend API version checks for cffi...
r32511 expected = _cextversions.get((pkgname, modname))
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 actual = getattr(mod, r'version', None)
if actual != expected:
raise ImportError(r'cannot import module %s.%s '
r'(expected version: %d, actual: %r)'
% (pkgname, modname, expected, actual))
def importmod(modname):
"""Import module according to policy and check API version"""
try:
verpkg, purepkg = _packageprefs[policy]
except KeyError:
raise ImportError(r'invalid HGMODULEPOLICY %r' % policy)
assert verpkg or purepkg
if verpkg:
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 pn, mn = _modredirects.get((verpkg, modname), (verpkg, modname))
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 try:
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 mod = _importfrom(pn, mn)
if pn == verpkg:
_checkmod(pn, mn, mod)
Yuya Nishihara
policy: add helper to import cext/pure module...
r32366 return mod
except ImportError:
if not purepkg:
raise
Yuya Nishihara
policy: reroute proxy modules internally...
r33755 pn, mn = _modredirects.get((purepkg, modname), (purepkg, modname))
return _importfrom(pn, mn)