def build(self, parent, filename, args, shared_args, emcc_args, native_args, native_exec, lib_builder, has_output_parser): self.parent = parent if lib_builder: env = { 'CC': self.cc, 'CXX': self.cxx, 'CXXFLAGS': "-Wno-c++11-narrowing" } env.update(clang_native.get_clang_native_env()) native_args = native_args + lib_builder( self.name, native=True, env_init=env) if not native_exec: compiler = self.cxx if filename.endswith('cpp') else self.cc cmd = [ compiler, '-fno-math-errno', filename, '-o', filename + '.native' ] + self.args + shared_args + native_args + clang_native.get_clang_native_args( ) # print(cmd) run_process(cmd, env=clang_native.get_clang_native_env()) else: shutil.copyfile(native_exec, filename + '.native') shutil.copymode(native_exec, filename + '.native') final = os.path.dirname( filename) + os.path.sep + self.name + '_' + os.path.basename( filename) + '.native' shutil.move(filename + '.native', final) self.filename = final
def __enter__(self): # compile the server # NOTE empty filename support is a hack to support # the current test_enet if self.filename: proc = run_process([ CLANG_CC, test_file(self.filename), '-o', 'server', '-DSOCKK=%d' % self.target_port ] + clang_native.get_clang_native_args() + self.args, clang_native.get_clang_native_env(), stdout=PIPE, stderr=PIPE) print('Socket server build: out:', proc.stdout or '', '/ err:', proc.stderr or '') process = Popen([os.path.abspath('server')]) self.processes.append(process) # start the websocket proxy print('running websockify on %d, forward to tcp %d' % (self.listen_port, self.target_port), file=sys.stderr) wsp = websockify.WebSocketProxy(verbose=True, listen_port=self.listen_port, target_host="127.0.0.1", target_port=self.target_port, run_once=True) self.websockify = multiprocessing.Process(target=wsp.start_server) self.websockify.start() self.processes.append(self.websockify) # Make sure both the actual server and the websocket proxy are running for i in range(10): try: if self.do_server_check: server_sock = socket.create_connection( ('localhost', self.target_port), timeout=1) server_sock.close() proxy_sock = socket.create_connection( ('localhost', self.listen_port), timeout=1) proxy_sock.close() break except IOError: time.sleep(1) else: clean_processes(self.processes) raise Exception( '[Websockify failed to start up in a timely manner]') print('[Websockify on process %s]' % str(self.processes[-2:]))
def run_benchmark(benchmark_file, results_file, build_args): # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CXX] + clang_native.get_clang_native_args() + [ benchmark_file, '-O3', '-o', out_file ] print('Building native version of the benchmark:') print(' '.join(cmd)) run_process(cmd, env=clang_native.get_clang_native_env()) native_results = Popen([out_file], stdout=PIPE, stderr=PIPE).communicate() print(native_results[0]) # Run emscripten build out_file = os.path.join(temp_dir, 'benchmark_sse_html.js') cmd = [ EMCC, benchmark_file, '-O3', '-s', 'TOTAL_MEMORY=536870912', '-o', out_file ] + build_args print('Building Emscripten version of the benchmark:') print(' '.join(cmd)) run_process(cmd) cmd = V8_ENGINE + ['--experimental-wasm-simd', os.path.basename(out_file)] print(' '.join(cmd)) old_dir = os.getcwd() os.chdir(os.path.dirname(out_file)) wasm_results = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate() os.chdir(old_dir) if not wasm_results: raise Exception('Unable to run benchmark in V8!') if not wasm_results[0].strip(): print(wasm_results[1]) sys.exit(1) print(wasm_results[0]) def strip_comments(text): return re.sub('//.*?\n|/\*.*?\*/', '', text, re.S) # noqa benchmark_results = strip_comments(wasm_results[0]) # Strip out unwanted print output. benchmark_results = benchmark_results[benchmark_results.find('{'):].strip() if '*************************' in benchmark_results: benchmark_results = benchmark_results[:benchmark_results.find( '*************************')].strip() print(benchmark_results) shutil.rmtree(temp_dir) native_results = json.loads(native_results[0]) benchmark_results = benchmark_results[ benchmark_results.index('{'):benchmark_results.rindex('}') + 1] wasm_results = json.loads(benchmark_results) # native_workload = native_results['workload'] # html_workload = wasm_results['workload'] html = '''<html><head></head><body><h1>SSE JavaScript Benchmark</h1> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/modules/exporting.js"></script><b>System Info:</b><br/> ''' + system_info[0].replace('\n', '<br/>') + ''' <b>Native Clang Compiler:</b><br/> ''' + native_info[1].replace('\n', '<br/>') + ''' <b>Emscripten Compiler:</b><br/> ''' + emscripten_info[0].replace('\n', '<br/>') charts_native = {} charts_html = {} for result in native_results['results']: ch = result['chart'] if ch not in charts_native: charts_native[ch] = [] charts_native[ch] += [result] for result in wasm_results['results']: ch = result['chart'] if ch not in charts_html: charts_html[ch] = [] charts_html[ch] += [result] def find_result_in_category(results, category): for result in results: if result['category'] == category: return result return None def format_comparison(a, b): if a < b and a != 0: return "<span style='color:green;font-weight:bold;'> {:10.2f}".format( b / a) + 'x FASTER</span>' elif b != 0: return "<span style='color:red;font-weight:bold;'> {:10.2f}".format( a / b) + 'x SLOWER</span>' else: return "<span style='color:red;font-weight:bold;'> NaN </span>" chartNumber = 0 total_time_native_scalar = 0 total_time_native_simd = 0 total_time_html_scalar = 0 total_time_html_simd = 0 for chart_name in charts_native.keys(): # Extract data for each chart. categories = [] nativeScalarResults = [] nativeSimdResults = [] htmlScalarResults = [] htmlSimdResults = [] native_results = charts_native[chart_name] wasm_results = charts_html[chart_name] textual_results_native = '<p>' textual_results_html = '<p>' textual_results_html2 = '<p>' textual_results_html3 = '<p>' for result in native_results: categories += ["'" + result['category'] + "'"] nsc = result['scalar'] nsi = result['simd'] nativeScalarResults += [str(nsc)] nativeSimdResults += [str(nsi)] html_result = find_result_in_category(wasm_results, result['category']) textual_results_native += 'Native ' + result[ 'category'] + ': ' + "{:10.4f}".format( nsc) + 'ns -> ' + "{:10.4f}".format(nsi) + 'ns. ' textual_results_native += 'Native SSE is ' + format_comparison( nsi, nsc ) + ' than native scalar. <br />' if html_result is not None: hsc = html_result['scalar'] htmlScalarResults += [str(hsc)] hsi = html_result['simd'] htmlSimdResults += [str(hsi)] textual_results_html += 'JS ' + result[ 'category'] + ': ' + "{:10.4f}".format( hsc) + 'ns -> ' + "{:10.4f}".format(hsi) + 'ns. ' textual_results_html += 'JS SSE is ' + format_comparison( hsi, hsc ) + ' than JS scalar. <br />' textual_results_html2 += 'JS ' + result[ 'category'] + ': JS scalar is ' + format_comparison( hsc, nsc ) + ' than native scalar. <br />' textual_results_html3 += 'JS ' + result[ 'category'] + ': JS SSE is ' + format_comparison( hsi, nsi ) + ' than native SSE. <br />' total_time_native_scalar += nsc total_time_native_simd += nsi total_time_html_scalar += hsc total_time_html_simd += hsi else: htmlScalarResults += [str(-1)] htmlSimdResults += [str(-1)] chartNumber += 1 html += '<div id="chart' + str( chartNumber ) + '" style="width:100%; height:400px; margin-top: 100px;"></div>' html += '''<script>$(function () { $('#chart''' + str(chartNumber) + '''').highcharts({ chart: { type: 'column' }, title: { text: "''' + chart_name + '''" }, subtitle: { text: 'Time per operation in nanoseconds' }, xAxis: { categories: [''' + ','.join(categories) + ''' ] }, yAxis: { min: 0, title: { text: 'Time (nanoseconds)' } }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.3f} ns</b></td></tr>', footerFormat: '</table>', shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0 } }, series: [{ name: 'Native scalar', data: [''' + ','.join(nativeScalarResults) + '''] }, { name: 'Native SSE', data: [''' + ','.join(nativeSimdResults) + '''] }, { name: 'JS scalar', data: [''' + ','.join(htmlScalarResults) + '''] }, { name: 'JS SSE', data: [''' + ','.join(htmlSimdResults) + '''] }] }); });</script>''' + '<table><tr><td>' + textual_results_native + '</td><td>' + textual_results_html + '</td></tr><tr><td>' + textual_results_html2 + '</td><td>' + textual_results_html3 + '</td></tr></table>' # Final overall score html += '<div id="overallscore" style="width:100%; height:400px; margin-top: 100px;"></div>' html += '''<script>$(function () { $('#overallscore').highcharts({ chart: { type: 'column' }, title: { text: "Overall Execution Time" }, xAxis: { categories: ['Total time normalized to native'] }, yAxis: { min: 0, title: { text: 'Relative time' } }, tooltip: { headerFormat: '<span style="font-size:10px">{point.key}</span><table>', pointFormat: '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' + '<td style="padding:0"><b>{point.y:.3f}x</b></td></tr>', footerFormat: '</table>', shared: true, useHTML: true }, plotOptions: { column: { pointPadding: 0.2, borderWidth: 0 } }, series: [{ name: 'Native scalar', data: [''' + str(1.0) + '''] }, { name: 'Native SSE', data: [''' + (str(total_time_native_simd / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }, { name: 'JS scalar', data: [''' + (str(total_time_html_scalar / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }, { name: 'JS SSE', data: [''' + (str(total_time_html_simd / total_time_native_scalar) if total_time_native_scalar != 0 else 'N/A') + '''] }] }); });</script>''' html += '</body></html>' open(results_file, 'w').write(html) print('Wrote ' + str(len(html)) + ' bytes to file ' + results_file + '.')