def __enter__(self): # assuming this is only used for WebSocket tests at the moment, validate that # the ws module is installed global npm_checked if not npm_checked: child = run_process(NODE_JS + ['-e', 'require("ws");'], check=False) assert child.returncode == 0, '"ws" node module not found. you may need to run npm install' npm_checked = True # compile the server proc = run_process([EMCC, path_from_root('tests', self.filename), '-o', 'server.js', '-DSOCKK=%d' % self.listen_port] + self.args) print('Socket server build: out:', proc.stdout or '', '/ err:', proc.stderr or '') process = Popen(NODE_JS + ['server.js']) self.processes.append(process)
def test_sdl_audio_mix_channels(self): shutil.copyfile(path_from_root('tests', 'sounds', 'noise.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) open(os.path.join(self.get_dir(), 'sdl_audio_mix_channels.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl_audio_mix_channels.c')).read())) Popen([ PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_mix_channels.c'), '--preload-file', 'sound.ogg', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl2_mixer(self): shutil.copyfile( path_from_root('tests', 'sounds', 'alarmvictory_1.ogg'), os.path.join(self.get_dir(), 'sound.ogg')) open(os.path.join(self.get_dir(), 'sdl2_mixer.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl2_mixer.c')).read())) Popen([ PYTHON, EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl2_mixer.c'), '-s', 'USE_SDL=2', '-s', 'USE_SDL_MIXER=2', '-s', 'TOTAL_MEMORY=33554432', '--preload-file', 'sound.ogg', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl_audio_panning(self): shutil.copyfile( path_from_root('tests', 'sounds', 'the_entertainer.wav'), os.path.join(self.get_dir(), 'the_entertainer.wav')) open(os.path.join(self.get_dir(), 'sdl_audio_panning.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl_audio_panning.c')).read())) # use closure to check for a possible bug with closure minifying away newer Audio() attributes Popen([ EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl_audio_panning.c'), '--preload-file', 'the_entertainer.wav', '-o', 'page.html', '-s', 'EXPORTED_FUNCTIONS=["_main", "_play"]' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_sdl2_mixer_wav(self): shutil.copyfile( path_from_root('tests', 'sounds', 'the_entertainer.wav'), os.path.join(self.get_dir(), 'sound.wav')) open(os.path.join(self.get_dir(), 'sdl2_mixer_wav.c'), 'w').write( self.with_report_result( open(path_from_root('tests', 'sdl2_mixer_wav.c')).read())) Popen([ EMCC, '-O2', '--minify', '0', os.path.join(self.get_dir(), 'sdl2_mixer_wav.c'), '-s', 'USE_SDL=2', '-s', 'USE_SDL_MIXER=2', '-s', 'INITIAL_MEMORY=33554432', '--preload-file', 'sound.wav', '-o', 'page.html' ]).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_freealut(self): Popen([EMCC, '-O2'] + self.get_freealut_library() + ['-o', 'page.html']).communicate() self.run_browser('page.html', 'You should hear "Hello World!"')
def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools import shared from tools.shared import PYTHON, WINDOWS, CLANG_CXX, EMCC, PIPE, V8_ENGINE from tools.shared import Popen temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse1_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CXX] + shared.Building.get_native_building_args() + [ path_from_root('tests', 'sse', 'benchmark_sse1.cpp'), '-O3', '-o', out_file ] print 'Building native version of the benchmark:'
def zzztest_sdl2_audio_beeps(self): open(os.path.join(self.get_dir(), 'sdl2_audio_beep.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl2_audio_beep.cpp')).read())) # use closure to check for a possible bug with closure minifying away newer Audio() attributes Popen([PYTHON, EMCC, '-O2', '--closure', '1', '--minify', '0', os.path.join(self.get_dir(), 'sdl2_audio_beep.cpp'), '-s', 'DISABLE_EXCEPTION_CATCHING=0', '-s', 'USE_SDL=2', '-o', 'page.html']).communicate() self.run_browser('page.html', '', '/report_result?1')
def test_webrtc(self): # XXX see src/settings.js, this is disabled pending investigation self.skipTest('WebRTC support is not up to date.') host_src = 'webrtc_host.c' peer_src = 'webrtc_peer.c' host_outfile = 'host.html' peer_outfile = 'peer.html' host_filepath = path_from_root('tests', 'sockets', host_src) temp_host_filepath = os.path.join(self.get_dir(), os.path.basename(host_src)) with open(host_filepath) as f: host_src = f.read() with open(temp_host_filepath, 'w') as f: f.write(self.with_report_result(host_src)) peer_filepath = path_from_root('tests', 'sockets', peer_src) temp_peer_filepath = os.path.join(self.get_dir(), os.path.basename(peer_src)) with open(peer_filepath) as f: peer_src = f.read() with open(temp_peer_filepath, 'w') as f: f.write(self.with_report_result(peer_src)) open(os.path.join(self.get_dir(), 'host_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: undefined, onpeer: function(peer, route) { window.open('http://localhost:8888/peer.html?' + route); // iframe = document.createElement("IFRAME"); // iframe.setAttribute("src", "http://localhost:8888/peer.html?" + route); // iframe.style.display = "none"; // document.body.appendChild(iframe); peer.listen(); }, onconnect: function(peer) { }, ondisconnect: function(peer) { }, onerror: function(error) { console.error(error); } }, setStatus: function(text) { console.log('status: ' + text); } }; ''') open(os.path.join(self.get_dir(), 'peer_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: window.location.toString().split('?')[1], onpeer: function(peer, route) { peer.connect(Module['webrtc']['session']); }, onconnect: function(peer) { }, ondisconnect: function(peer) { // Calling window.close() from this handler hangs my browser, so run it in the next turn setTimeout(window.close, 0); }, onerror: function(error) { console.error(error); }, }, setStatus: function(text) { console.log('status: ' + text); } }; ''') run_process([EMCC, temp_host_filepath, '-o', host_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'host_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) run_process([EMCC, temp_peer_filepath, '-o', peer_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'peer_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) # note: you may need to run this manually yourself, if npm is not in the path, or if you need a version that is not in the path run_process([NPM, 'install', path_from_root('tests', 'sockets', 'p2p')]) broker = Popen(NODE_JS + [path_from_root('tests', 'sockets', 'p2p', 'broker', 'p2p-broker.js')]) expected = '1' self.run_browser(host_outfile, '.', ['/report_result?' + e for e in expected]) broker.kill()
def __enter__(self): print('Running background server: ' + str(self.args)) process = Popen(self.args) self.processes.append(process)
def test_webrtc(self): # XXX see src/settings.js, this is disabled pending investigation self.skipTest('WebRTC support is not up to date.') host_src = 'webrtc_host.c' peer_src = 'webrtc_peer.c' host_outfile = 'host.html' peer_outfile = 'peer.html' host_filepath = path_from_root('tests', 'sockets', host_src) temp_host_filepath = os.path.join(self.get_dir(), os.path.basename(host_src)) with open(host_filepath) as f: host_src = f.read() with open(temp_host_filepath, 'w') as f: f.write(self.with_report_result(host_src)) peer_filepath = path_from_root('tests', 'sockets', peer_src) temp_peer_filepath = os.path.join(self.get_dir(), os.path.basename(peer_src)) with open(peer_filepath) as f: peer_src = f.read() with open(temp_peer_filepath, 'w') as f: f.write(self.with_report_result(peer_src)) open(os.path.join(self.get_dir(), 'host_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: undefined, onpeer: function(peer, route) { window.open('http://localhost:8888/peer.html?' + route); // iframe = document.createElement("IFRAME"); // iframe.setAttribute("src", "http://localhost:8888/peer.html?" + route); // iframe.style.display = "none"; // document.body.appendChild(iframe); peer.listen(); }, onconnect: function(peer) { }, ondisconnect: function(peer) { }, onerror: function(error) { console.error(error); } }, setStatus: function(text) { console.log('status: ' + text); } }; ''') open(os.path.join(self.get_dir(), 'peer_pre.js'), 'w').write(''' var Module = { webrtc: { broker: 'http://localhost:8182', session: window.location.toString().split('?')[1], onpeer: function(peer, route) { peer.connect(Module['webrtc']['session']); }, onconnect: function(peer) { }, ondisconnect: function(peer) { // Calling window.close() from this handler hangs my browser, so run it in the next turn setTimeout(window.close, 0); }, onerror: function(error) { console.error(error); }, }, setStatus: function(text) { console.log('status: ' + text); } }; ''') run_process([PYTHON, EMCC, temp_host_filepath, '-o', host_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'host_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) run_process([PYTHON, EMCC, temp_peer_filepath, '-o', peer_outfile] + ['-s', 'GL_TESTING=1', '--pre-js', 'peer_pre.js', '-s', 'SOCKET_WEBRTC=1', '-s', 'SOCKET_DEBUG=1']) # note: you may need to run this manually yourself, if npm is not in the path, or if you need a version that is not in the path run_process([NPM, 'install', path_from_root('tests', 'sockets', 'p2p')]) broker = Popen(NODE_JS + [path_from_root('tests', 'sockets', 'p2p', 'broker', 'p2p-broker.js')]) expected = '1' self.run_browser(host_outfile, '.', ['/report_result?' + e for e in expected]) broker.kill()
# System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([PYTHON, EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse1_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CPP] + get_clang_native_args() + [path_from_root('tests', 'benchmark_sse1.cpp'), '-O3', '-o', out_file] print 'Building native version of the benchmark:' print ' '.join(cmd) build = Popen(cmd, env=get_clang_native_env()) out = build.communicate() if build.returncode != 0: sys.exit(1) 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_sse1_html.html') cmd = [PYTHON, EMCC, path_from_root('tests', 'benchmark_sse1.cpp'), '-O3', '-msse', '--emrun', '-s', 'TOTAL_MEMORY=536870912', '-o', out_file] print 'Building Emscripten version of the benchmark:' print ' '.join(cmd) build = Popen(cmd) out = build.communicate() if build.returncode != 0:
__rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools.shared import PYTHON, WINDOWS, CLANG_CPP, EMCC, PIPE from tools.shared import Popen, get_clang_native_args, get_clang_native_env temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([PYTHON, EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() # Run native build out_file = os.path.join(temp_dir, 'benchmark_sse1_native') if WINDOWS: out_file += '.exe' cmd = [CLANG_CPP] + get_clang_native_args() + [ path_from_root('tests', 'benchmark_sse1.cpp'), '-O3', '-o', out_file ]
def test_openal_playback(self): shutil.copyfile(path_from_root('tests', 'sounds', 'audio.wav'), os.path.join(self.get_dir(), 'audio.wav')) open(os.path.join(self.get_dir(), 'openal_playback.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'openal_playback.cpp')).read())) Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'openal_playback.cpp'), '--preload-file', 'audio.wav', '-o', 'page.html']).communicate() self.run_browser('page.html', '', '/report_result?1')
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] + building.get_native_building_args() + [ benchmark_file, '-O3', '-o', out_file ] print 'Building native version of the benchmark:' print ' '.join(cmd) build = Popen(cmd, env=building.get_building_env(native=True)) out = build.communicate() if build.returncode != 0: sys.exit(1) 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) build = Popen(cmd) out = build.communicate() if build.returncode != 0: sys.exit(1) 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) 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 + '.'
def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) sys.path += [path_from_root('')] from tools import shared, building from tools.shared import PYTHON, WINDOWS, CLANG_CXX, EMCC, PIPE, V8_ENGINE from tools.shared import Popen temp_dir = tempfile.mkdtemp() # System info system_info = Popen([PYTHON, path_from_root('emrun'), '--system_info'], stdout=PIPE, stderr=PIPE).communicate() # Native info native_info = Popen(['clang', '-v'], stdout=PIPE, stderr=PIPE).communicate() # Emscripten info emscripten_info = Popen([EMCC, '-v'], stdout=PIPE, stderr=PIPE).communicate() 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] + building.get_native_building_args() + [ benchmark_file, '-O3', '-o', out_file