Mercurial > piecrust2
comparison piecrust/baking/single.py @ 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 | 3e4049022869 |
children | ab5c6a8ae90a |
comparison
equal
deleted
inserted
replaced
701:066d6156525c | 702:c62d83e17abf |
---|---|
1 import os.path | 1 import os.path |
2 import queue | |
2 import shutil | 3 import shutil |
3 import logging | 4 import logging |
5 import threading | |
4 import urllib.parse | 6 import urllib.parse |
5 from piecrust import ASSET_DIR_SUFFIX | 7 from piecrust import ASSET_DIR_SUFFIX |
6 from piecrust.baking.records import SubPageBakeInfo | 8 from piecrust.baking.records import SubPageBakeInfo |
7 from piecrust.rendering import ( | 9 from piecrust.rendering import ( |
8 QualifiedPage, PageRenderingContext, render_page, | 10 QualifiedPage, PageRenderingContext, render_page, |
13 logger = logging.getLogger(__name__) | 15 logger = logging.getLogger(__name__) |
14 | 16 |
15 | 17 |
16 class BakingError(Exception): | 18 class BakingError(Exception): |
17 pass | 19 pass |
20 | |
21 | |
22 def _text_writer(q): | |
23 while True: | |
24 item = q.get() | |
25 if item is not None: | |
26 out_path, txt = item | |
27 out_dir = os.path.dirname(out_path) | |
28 _ensure_dir_exists(out_dir) | |
29 | |
30 with open(out_path, 'w', encoding='utf8') as fp: | |
31 fp.write(txt) | |
32 | |
33 q.task_done() | |
34 else: | |
35 # Sentinel object, terminate the thread. | |
36 q.task_done() | |
37 break | |
18 | 38 |
19 | 39 |
20 class PageBaker(object): | 40 class PageBaker(object): |
21 def __init__(self, app, out_dir, force=False, copy_assets=True): | 41 def __init__(self, app, out_dir, force=False, copy_assets=True): |
22 self.app = app | 42 self.app = app |
23 self.out_dir = out_dir | 43 self.out_dir = out_dir |
24 self.force = force | 44 self.force = force |
25 self.copy_assets = copy_assets | 45 self.copy_assets = copy_assets |
26 self.site_root = app.config.get('site/root') | 46 self.site_root = app.config.get('site/root') |
27 self.pretty_urls = app.config.get('site/pretty_urls') | 47 self.pretty_urls = app.config.get('site/pretty_urls') |
48 self._writer_queue = queue.Queue() | |
49 self._writer = threading.Thread( | |
50 name='PageSerializer', | |
51 target=_text_writer, | |
52 args=(self._writer_queue,)) | |
53 self._writer.start() | |
54 | |
55 def shutdown(self): | |
56 self._writer_queue.put_nowait(None) | |
57 self._writer.join() | |
28 | 58 |
29 def getOutputPath(self, uri): | 59 def getOutputPath(self, uri): |
30 uri_root, uri_path = split_uri(self.app, uri) | 60 uri_root, uri_path = split_uri(self.app, uri) |
31 | 61 |
32 bake_path = [self.out_dir] | 62 bake_path = [self.out_dir] |
160 | 190 |
161 with self.app.env.timerScope("PageRender"): | 191 with self.app.env.timerScope("PageRender"): |
162 rp = render_page(ctx) | 192 rp = render_page(ctx) |
163 | 193 |
164 with self.app.env.timerScope("PageSerialize"): | 194 with self.app.env.timerScope("PageSerialize"): |
165 out_dir = os.path.dirname(out_path) | 195 self._writer_queue.put_nowait((out_path, rp.content)) |
166 _ensure_dir_exists(out_dir) | |
167 | |
168 with open(out_path, 'w', encoding='utf8') as fp: | |
169 fp.write(rp.content) | |
170 | 196 |
171 return rp | 197 return rp |
172 | 198 |
173 | 199 |
174 def _compute_force_flags(prev_sub_entry, sub_entry, dirty_source_names): | 200 def _compute_force_flags(prev_sub_entry, sub_entry, dirty_source_names): |