# HG changeset patch # User Ludovic Chabant # Date 1413704008 25200 # Node ID 371a6c879ab966ba995826ca22814bc513a3e2b4 # Parent de257cc40ce1f501fb4efbeca4fdba3d3d4b5b51 When possible, try and batch-load pages so we only lock once. diff -r de257cc40ce1 -r 371a6c879ab9 piecrust/data/provider.py --- a/piecrust/data/provider.py Sun Oct 19 00:30:44 2014 -0700 +++ b/piecrust/data/provider.py Sun Oct 19 00:33:28 2014 -0700 @@ -117,8 +117,7 @@ return self._yearly self._yearly = [] - for fac in self._source.getPageFactories(): - post = fac.buildPage() + for post in self._source.getPages(): year = post.datetime.strftime('%Y') posts_this_year = next( @@ -142,8 +141,7 @@ return self._monthly self._monthly = [] - for fac in self._source.getPageFactories(): - post = fac.buildPage() + for post in self._source.getPages(): month = post.datetime.strftime('%B %Y') posts_this_month = next( @@ -168,8 +166,7 @@ return self._taxonomies[tax_name] posts_by_tax_value = {} - for fac in self._source.getPageFactories(): - post = fac.buildPage() + for post in self._source.getPages(): tax_values = post.config.get(tax_name) if tax_values is None: continue diff -r de257cc40ce1 -r 371a6c879ab9 piecrust/environment.py --- a/piecrust/environment.py Sun Oct 19 00:30:44 2014 -0700 +++ b/piecrust/environment.py Sun Oct 19 00:33:28 2014 -0700 @@ -3,6 +3,7 @@ import json import logging import threading +import contextlib import collections import repoze.lru @@ -23,12 +24,19 @@ """ def __init__(self, size=2048): self.cache = repoze.lru.LRUCache(size) - self.lock = threading.RLock() self.fs_cache = None self._invalidated_fs_items = set() + self._lock = threading.RLock() + + @contextlib.contextmanager + def startBatchGet(self): + logger.debug("Starting batch cache operation.") + with self._lock: + yield + logger.debug("Ending batch cache operation.") def invalidate(self, key): - with self.lock: + with self._lock: logger.debug("Invalidating cache item '%s'." % key) self.cache.invalidate(key) if self.fs_cache: @@ -40,7 +48,7 @@ item = self.cache.get(key) if item is None: logger.debug("Acquiring lock for: %s" % key) - with self.lock: + with self._lock: item = self.cache.get(key) if item is None: if (self.fs_cache is not None and @@ -107,19 +115,27 @@ def popPage(self): del self._page_stack[-1] + def clear(self): + self._page_stack = [] + class Environment(object): def __init__(self): - self.start_time = time.clock() + self.start_time = None self.exec_info_stack = ExecutionInfoStack() self.was_cache_cleaned = False + self.base_asset_url_format = '%uri%' self.page_repository = MemCache() self.rendered_segments_repository = MemCache() self.fs_caches = { 'renders': self.rendered_segments_repository} + + def initialize(self, app): + self.start_time = time.clock() + self.exec_info_stack.clear() + self.was_cache_cleaned = False self.base_asset_url_format = '%uri%' - def initialize(self, app): for name, repo in self.fs_caches.items(): cache = app.cache.getCache(name) repo.fs_cache = cache diff -r de257cc40ce1 -r 371a6c879ab9 piecrust/processing/sitemap.py --- a/piecrust/processing/sitemap.py Sun Oct 19 00:30:44 2014 -0700 +++ b/piecrust/processing/sitemap.py Sun Oct 19 00:33:28 2014 -0700 @@ -65,11 +65,10 @@ if source is None: raise Exception("No such source: %s" % name) - for fac in source.getPageFactories(): - route = self.app.getRoute(source.name, fac.metadata) - uri = route.getUri(fac.metadata) + for page in source.getPages(): + route = self.app.getRoute(source.name, page.source_metadata) + uri = route.getUri(page.source_metadata) - page = fac.buildPage() t = page.datetime.timestamp() sm_cfg = page.config.get('sitemap') diff -r de257cc40ce1 -r 371a6c879ab9 piecrust/sources/base.py --- a/piecrust/sources/base.py Sun Oct 19 00:30:44 2014 -0700 +++ b/piecrust/sources/base.py Sun Oct 19 00:33:28 2014 -0700 @@ -26,6 +26,12 @@ page_ref_pattern = re.compile(r'(?P[\w]+)\:(?P.*?)(;|$)') +def build_pages(app, factories): + with app.env.page_repository.startBatchGet(): + for f in factories: + yield f.buildPage() + + class PageNotFoundError(Exception): pass @@ -207,6 +213,9 @@ return self.app.theme_dir return self.app.root_dir + def getPages(self): + return build_pages(self.app, self.getPageFactories()) + def getPageFactories(self): if self._factories is None: self._factories = list(self.buildPageFactories()) @@ -383,8 +392,7 @@ # iterator chain. It acts as the end. def __iter__(self): - for factory in self.source.getPageFactories(): - yield factory.buildPage() + return self.source.getPages() class DateSortIterator(object):