Implement profiling of book preparation

Cache href_to_name() which was marked as a hot function by the profiler.
This commit is contained in:
Kovid Goyal 2019-10-26 18:19:32 +05:30
parent 60a1f637c5
commit 751c6942f9
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 39 additions and 2 deletions

View File

@ -60,6 +60,7 @@ exists, join, relpath = os.path.exists, os.path.join, os.path.relpath
OEB_FONTS = {guess_type('a.ttf'), guess_type('b.otf'), guess_type('a.woff'), 'application/x-font-ttf', 'application/x-font-otf', 'application/font-sfnt'}
OPF_NAMESPACES = {'opf':OPF2_NS, 'dc':DC11_NS}
null = object()
class CSSPreProcessor(cssp):
@ -261,6 +262,7 @@ class Container(ContainerBase): # {{{
self.pretty_print = set()
self.cloned = False
self.cache_names = ('parsed_cache', 'mime_map', 'name_path_map', 'encoding_map', 'dirtied', 'pretty_print')
self.href_to_name_cache = {}
if clone_data is not None:
self.cloned = True
@ -524,7 +526,11 @@ class Container(ContainerBase): # {{{
Convert an href (relative to base) to a name. base must be a name or
None, in which case self.root is used.
'''
return href_to_name(href, self.root, base=base)
key = href, base
ans = self.href_to_name_cache.get(key, null)
if ans is null:
ans = self.href_to_name_cache[key] = href_to_name(href, self.root, base=base)
return ans
def name_to_href(self, name, base=None):
'''Convert a name to a href relative to base, which must be a name or

View File

@ -880,5 +880,36 @@ def viewer_main():
render_for_viewer(*args)
class Profiler(object):
def __init__(self):
try:
import cProfile as profile
except ImportError:
import profile
self.profile = profile.Profile()
def __enter__(self):
self.profile.enable()
def __exit__(self, *a):
self.profile.disable()
self.profile.create_stats()
import pstats
stats = pstats.Stats(self.profile)
stats.sort_stats('cumulative')
stats.print_stats(.05)
def profile():
from calibre.ptempfile import TemporaryDirectory
path = sys.argv[-1]
with TemporaryDirectory() as tdir, Profiler():
return render(
path, tdir, serialize_metadata=True,
extract_annotations=True, virtualize_resources=False, max_workers=1
)
if __name__ == '__main__':
render_for_viewer(sys.argv[-2], sys.argv[-1], None)
profile()