Mercurial > piecrust2
changeset 702:c62d83e17abf
bake: Some more optimizations.
Write the output files in a background thread to get away from the GIL.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 16 Apr 2016 22:50:07 -0700 |
parents | 066d6156525c |
children | dab26ab3d533 |
files | piecrust/baking/single.py piecrust/baking/worker.py piecrust/workerpool.py |
diffstat | 3 files changed, 46 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/baking/single.py Sat Apr 16 22:48:57 2016 -0700 +++ b/piecrust/baking/single.py Sat Apr 16 22:50:07 2016 -0700 @@ -1,6 +1,8 @@ import os.path +import queue import shutil import logging +import threading import urllib.parse from piecrust import ASSET_DIR_SUFFIX from piecrust.baking.records import SubPageBakeInfo @@ -17,6 +19,24 @@ pass +def _text_writer(q): + while True: + item = q.get() + if item is not None: + out_path, txt = item + out_dir = os.path.dirname(out_path) + _ensure_dir_exists(out_dir) + + with open(out_path, 'w', encoding='utf8') as fp: + fp.write(txt) + + q.task_done() + else: + # Sentinel object, terminate the thread. + q.task_done() + break + + class PageBaker(object): def __init__(self, app, out_dir, force=False, copy_assets=True): self.app = app @@ -25,6 +45,16 @@ self.copy_assets = copy_assets self.site_root = app.config.get('site/root') self.pretty_urls = app.config.get('site/pretty_urls') + self._writer_queue = queue.Queue() + self._writer = threading.Thread( + name='PageSerializer', + target=_text_writer, + args=(self._writer_queue,)) + self._writer.start() + + def shutdown(self): + self._writer_queue.put_nowait(None) + self._writer.join() def getOutputPath(self, uri): uri_root, uri_path = split_uri(self.app, uri) @@ -162,11 +192,7 @@ rp = render_page(ctx) with self.app.env.timerScope("PageSerialize"): - out_dir = os.path.dirname(out_path) - _ensure_dir_exists(out_dir) - - with open(out_path, 'w', encoding='utf8') as fp: - fp.write(rp.content) + self._writer_queue.put_nowait((out_path, rp.content)) return rp
--- a/piecrust/baking/worker.py Sat Apr 16 22:48:57 2016 -0700 +++ b/piecrust/baking/worker.py Sat Apr 16 22:50:07 2016 -0700 @@ -81,6 +81,10 @@ 'type': 'stats', 'data': data} + def shutdown(self): + for jh in self.job_handlers.values(): + jh.shutdown() + JOB_LOAD, JOB_RENDER_FIRST, JOB_BAKE = range(0, 3) @@ -96,6 +100,9 @@ def handleJob(self, job): raise NotImplementedError() + def shutdown(self): + pass + def _get_errors(ex): errors = [] @@ -183,6 +190,9 @@ super(BakeJobHandler, self).__init__(ctx) self.page_baker = PageBaker(ctx.app, ctx.out_dir, ctx.force) + def shutdown(self): + self.page_baker.shutdown() + def handleJob(self, job): # Actually bake the page and all its sub-pages to the output folder. fac = load_factory(self.app, job['factory_info'])
--- a/piecrust/workerpool.py Sat Apr 16 22:48:57 2016 -0700 +++ b/piecrust/workerpool.py Sat Apr 16 22:50:07 2016 -0700 @@ -26,6 +26,9 @@ def getReport(self, pool_reports): return None + def shutdown(self): + pass + TASK_JOB = 0 TASK_BATCH = 1 @@ -149,6 +152,8 @@ reader_thread.join() writer_thread.join() + w.shutdown() + logger.debug("Worker %d completed %d tasks." % (wid, completed))