changeset 114:371a6c879ab9

When possible, try and batch-load pages so we only lock once.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 19 Oct 2014 00:33:28 -0700
parents de257cc40ce1
children 9c074aec60a6
files piecrust/data/provider.py piecrust/environment.py piecrust/processing/sitemap.py piecrust/sources/base.py
diffstat 4 files changed, 37 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
--- 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')
 
--- 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<src>[\w]+)\:(?P<path>.*?)(;|$)')
 
 
+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):