Mercurial > piecrust2
comparison piecrust/commands/builtin/baking.py @ 989:8adc27285d93
bake: Big pass on bake performance.
- Reduce the amount of data passed between processes.
- Make inter-process data simple objects to make it easier to test with
alternatives to pickle.
- Make sources have the basic requirement to be able to find a content item
from an item spec (path).
- Make Hoedown the default Markdown formatter.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 19 Nov 2017 14:29:17 -0800 |
parents | f83ae0a5d793 |
children | 3c669bb9498e |
comparison
equal
deleted
inserted
replaced
988:f83ae0a5d793 | 989:8adc27285d93 |
---|---|
46 action='store_true') | 46 action='store_true') |
47 parser.add_argument( | 47 parser.add_argument( |
48 '--show-stats', | 48 '--show-stats', |
49 help="Show detailed information about the bake.", | 49 help="Show detailed information about the bake.", |
50 action='store_true') | 50 action='store_true') |
51 parser.add_argument( | |
52 '--profile', | |
53 help="Run the bake several times, for profiling.", | |
54 type=int, default=-1) | |
51 | 55 |
52 def run(self, ctx): | 56 def run(self, ctx): |
53 from piecrust.chefutil import format_timed | 57 from piecrust.chefutil import format_timed |
58 from piecrust.environment import ExecutionStats | |
54 | 59 |
55 out_dir = (ctx.args.output or | 60 out_dir = (ctx.args.output or |
56 os.path.join(ctx.app.root_dir, '_counter')) | 61 os.path.join(ctx.app.root_dir, '_counter')) |
57 | 62 |
63 success = True | |
64 avg_stats = ExecutionStats() | |
65 avg_stats.registerTimer('Total') | |
58 start_time = time.perf_counter() | 66 start_time = time.perf_counter() |
59 try: | 67 |
60 records = self._doBake(ctx, out_dir) | 68 num_iter = 1 |
61 | 69 if ctx.args.profile > 0: |
62 # Show merged stats. | 70 num_iter = ctx.args.profile |
63 if ctx.args.show_stats: | 71 |
64 logger.info("-------------------") | 72 for i in range(num_iter): |
65 logger.info("Timing information:") | 73 iter_start_time = time.perf_counter() |
66 _show_stats(records.stats) | 74 if num_iter > 1: |
67 | 75 import gc |
68 # All done. | 76 gc.collect() |
69 logger.info('-------------------------') | 77 logger.info("---- %d/%d ----" % (i + 1, num_iter)) |
70 logger.info(format_timed(start_time, 'done baking')) | 78 |
71 return 0 if records.success else 1 | 79 try: |
72 except Exception as ex: | 80 records = self._doBake(ctx, out_dir) |
73 if ctx.app.debug: | 81 except Exception as ex: |
74 logger.exception(ex) | 82 if ctx.app.debug: |
75 else: | 83 logger.exception(ex) |
76 logger.error(str(ex)) | 84 else: |
77 return 1 | 85 logger.error(str(ex)) |
86 return 1 | |
87 | |
88 success = success and records.success | |
89 avg_stats.mergeStats(records.stats) | |
90 avg_stats.stepTimerSince('Total', iter_start_time) | |
91 | |
92 # Show merged stats. | |
93 if ctx.args.show_stats: | |
94 if num_iter > 1: | |
95 _average_stats(avg_stats, num_iter) | |
96 | |
97 logger.info("-------------------") | |
98 logger.info("Timing information:") | |
99 _show_stats(avg_stats) | |
100 | |
101 # All done. | |
102 logger.info('-------------------------') | |
103 logger.info(format_timed(start_time, 'done baking')) | |
104 return 0 if success else 1 | |
78 | 105 |
79 def _doBake(self, ctx, out_dir): | 106 def _doBake(self, ctx, out_dir): |
80 from piecrust.baking.baker import Baker | 107 from piecrust.baking.baker import Baker |
81 | 108 |
82 if ctx.args.workers > 0: | 109 if ctx.args.workers > 0: |
249 | 276 |
250 if entries_to_show: | 277 if entries_to_show: |
251 logger.info("Record: %s" % rec.name) | 278 logger.info("Record: %s" % rec.name) |
252 logger.info("Status: %s" % ('SUCCESS' if rec.success | 279 logger.info("Status: %s" % ('SUCCESS' if rec.success |
253 else 'FAILURE')) | 280 else 'FAILURE')) |
281 logger.info("User Data:") | |
282 if not rec.user_data: | |
283 logger.info(" <empty>") | |
284 else: | |
285 for k, v in rec.user_data.items(): | |
286 logger.info(" %s: %s" % (k, v)) | |
287 | |
254 for e in entries_to_show: | 288 for e in entries_to_show: |
255 _print_record_entry(e) | 289 _print_record_entry(e) |
256 logger.info("") | 290 logger.info("") |
257 | 291 |
258 stats = records.stats | 292 stats = records.stats |
268 (Fore.CYAN, name, Fore.RESET, len(val))) | 302 (Fore.CYAN, name, Fore.RESET, len(val))) |
269 for v in val: | 303 for v in val: |
270 logger.info(" - %s" % v) | 304 logger.info(" - %s" % v) |
271 | 305 |
272 | 306 |
307 def _average_stats(stats, cnt): | |
308 for name in stats.timers: | |
309 stats.timers[name] /= cnt | |
310 for name in stats.counters: | |
311 stats.counters[name] /= cnt | |
312 | |
313 | |
273 def _show_stats(stats, *, full=False): | 314 def _show_stats(stats, *, full=False): |
274 indent = ' ' | 315 indent = ' ' |
275 | 316 |
276 logger.info(' Timers:') | 317 logger.info(' Timers:') |
277 for name, val in sorted(stats.timers.items(), key=lambda i: i[1], | 318 for name, val in sorted(stats.timers.items(), key=lambda i: i[1], |