diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-10-28 18:25:35 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-10-28 18:25:35 -0700 |
commit | 2c05adf81582be5216e28198b0a104b21dabf835 (patch) | |
tree | 3a229b4e96899039884574d961d48b9d70a4566c /tools/js_optimizer.py | |
parent | dcc877f3bd1137c40ccf48c674b52084a93379db (diff) |
split out js_optimizer python portion into an independent module
Diffstat (limited to 'tools/js_optimizer.py')
-rw-r--r-- | tools/js_optimizer.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py new file mode 100644 index 00000000..3fdabfa8 --- /dev/null +++ b/tools/js_optimizer.py @@ -0,0 +1,78 @@ + +import os, sys, subprocess, multiprocessing + +__rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +def path_from_root(*pathelems): + return os.path.join(__rootpath__, *pathelems) + +JS_OPTIMIZER = path_from_root('tools', 'js-optimizer.js') + +BEST_JS_PROCESS_SIZE = 1024*1024 + +def run_on_chunk(command): + filename = command[2] # XXX hackish + output = subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0] + assert len(output) > 0 and not output.startswith('Assertion failed'), 'Error in js optimizer: ' + output + filename += '.jo.js' + f = open(filename, 'w') + f.write(output) + f.close() + return filename + +def run(filename, passes, js_engine): + if type(passes) == str: + passes = [passes] + + js = open(filename).read() + + # Find suffix + suffix_marker = '// EMSCRIPTEN_GENERATED_FUNCTIONS' + suffix_start = js.find(suffix_marker) + suffix = '' + if suffix_start >= 0: + suffix = js[suffix_start:js.find('\n', suffix_start)] + '\n' + + # Pick where to split into chunks, so that (1) they do not oom in node/uglify, and (2) we can run them in parallel + chunks = [] + i = 0 + f_start = 0 + while True: + f_end = f_start + while f_end-f_start < BEST_JS_PROCESS_SIZE and f_end != -1: + f_end = js.find('\n}\n', f_end+1) + chunk = js[f_start:(-1 if f_end == -1 else f_end+3)] + suffix + temp_file = filename + '.p%d.js' % i + i += 1 + f_start = f_end+3 + done = f_end == -1 or f_start >= len(js) + if done and len(chunks) == 0: break # do not write anything out, just use the input file + f = open(temp_file, 'w') + f.write(chunk) + f.close() + chunks.append(temp_file) + if done: break + + if len(chunks) == 0: + chunks.append(filename) + + # XXX Use '--nocrankshaft' to disable crankshaft to work around v8 bug 1895, needed for older v8/node (node 0.6.8+ should be ok) + commands = map(lambda chunk: [js_engine, JS_OPTIMIZER, chunk] + passes, chunks) + + if len(chunks) > 1: + cores = min(multiprocessing.cpu_count(), chunks) + if os.environ.get('EMCC_DEBUG'): print >> sys.stderr, 'splitting up js optimization into %d chunks, using %d cores' % (len(chunks), cores) + pool = multiprocessing.Pool(processes=cores) + commands = map(lambda command: command + ['noPrintMetadata'], commands) + filenames = pool.map(run_on_chunk, commands, chunksize=1) + filename += '.jo.js' + f = open(filename, 'w') + for out_file in filenames: + f.write(open(out_file).read()) + f.write(suffix) + f.write('\n') + f.close() + return filename + else: + # one simple chunk, just do it + return run_on_chunk(commands[0]) + |