3 Star 0 Fork 0

mirrors_kripken/talks

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
binaryen.html 16.75 KB
一键复制 编辑 原始数据 按行查看 历史
Alon Zakai 提交于 2016-06-19 03:17 +08:00 . fix title
<html lang="en">
<head>
<meta charset="utf-8">
<title>Compiling to WebAssembly with Binaryen</title>
<meta name="description" content="Compiling to WebAssembly with Binaryen">
<meta name="author" content="Alon Zakai">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link rel="stylesheet" href="css/reveal.min.css">
<link rel="stylesheet" href="css/theme/beige.css" id="theme">
<!-- For syntax highlighting -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<!-- If the query includes 'print-pdf', use the PDF print sheet -->
<script>
document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
<style type="text/css">
h2 b {
color: #048;
}
h3 b {
color: #369;
}
b {
color: #c64;
}
strong {
color: #c11;
}
</style>
<style type="text/css">
#wrap {
width:600px;
margin:0 auto;
}
#left_col {
float:left;
width:300px;
}
#right_col {
float:right;
width:300px;
}
</style>
</head>
<body>
<div class="reveal">
<!-- Any section element inside of this container is displayed as a slide -->
<div class="slides">
<section>
<h1>Compiling to<br>WebAssembly<br>with Binaryen</h1>
<br>
<p><b>Alon Zakai</b> / <a style="" href="http://twitter.com/#!/kripken">@kripken</a></p>
<p>June 2016</p>
</section>
<section>
<h3>Background: WebAssembly</h3>
<br>
<p><a href="https://github.com/WebAssembly/design">WebAssembly</a> (wasm) is a new <b>binary executable format</b></a></p>
<br>
<p class="fragment">Will allow even large compiled codebases to run efficiently on the web, even better than <a href="http://asmjs.org/">asm.js</a></p>
<br>
<p class="fragment">Main initial focus is on <b>C and C++</b>, since those are very popular (e.g., in the games space: Unity, Unreal, etc.), but not only</p>
</section>
<section>
<h3>Background: Binaryen</h3>
<br>
<p><a href="https://github.com/WebAssembly/binaryen">Binaryen</a> is a <b>compiler and toolchain library</b> for WebAssembly, in <strong>C++</strong></p>
<br>
<p class="fragment"><b>Read, write, and transform</b> wasm</p>
<br>
<p class="fragment">Used with clang+LLVM+emscripten for <b>C/C++ &rArr; wasm</b></p>
<br>
<p class="fragment">Does wasm <b>minification</b>, like we have minifiers for JavaScript, CSS, etc.</p>
<br>
<p class="fragment">Does <b>general-purpose optimizations</b> like dead code elimination, etc.</p>
</section>
<section>
<p><b>Partial list of Binaryen's optimization passes</b></p>
<hr>
<ul>
<li>Local coloring</li>
<li>Local stacking</li>
<li>Block/if return value opts</li>
<li>Dead code elimination</li>
<li>Duplicate function elimination</li>
<li>Local reordering</li>
<li>...</li>
</ul>
<hr>
</section>
<!--
<section>
<h3>Compiling C++ to wasm</h3>
<p>Using <a href="http://emscripten.org">emscripten</a> and <a href="https://llvm.org/">LLVM</a>+<a href="http://clang.llvm.org/">clang</a>, currently two options:</p>
<br>
<p style="background-color: black; padding: 0.4em; box-shadow: 8px 8px 8px rgba(0,0,0,0.6)"><b style="color: #f42">C++</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #7af">clang</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #8f5">asm.js backend</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #f58">asm2wasm</b><b style="color: #fff">&nbsp&nbsp&rArr;</b>&nbsp&nbsp<b style="color: #f42">wasm</b></p>
<br>
<p style="background-color: black; padding: 0.4em; box-shadow: 8px 8px 8px rgba(0,0,0,0.6)"><b style="color: #f42">C++</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #7af">clang</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #8f5">wasm backend</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #f58">s2wasm</b><b style="color: #fff">&nbsp&nbsp&rArr;</b>&nbsp&nbsp<b style="color: #f42">wasm</b></p>
<br>
<p class="fragment">asm.js and wasm backends are <b>LLVM backends</b></p>
<br>
<p class="fragment"><b>asm2wasm</b> and <b>s2wasm</b> are from Binaryen</p>
</section>
<section>
<p>Why <strong>two</strong> LLVM backends, asm.js and wasm?</p>
<br>
<p class="fragment">asm.js backend already existed, <a href="https://kripken.github.io/talks/wasm.html#/">asm2wasm easy to add</a></p>
<br>
<p class="fragment">asm2wasm <b>already works and is pretty stable</b></a>
</section>
<section>
<p>The wasm backend is <b>still in development</b>, but <b>should be better</b> than the asm.js one:</p>
<br>
<p class="fragment">Full i64 support</p>
<br>
<p class="fragment">Supports all LLVM IR (full legalization)</p>
<br>
<p class="fragment">LLVM's codegen can emit very good code</p>
<br>
<p class="fragment">Developed upstream</p>
</section>
<section>
<p>However, wasm backend compiles more slowly, due to known LLVM codegen issues (e.g., <a href="https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/">WebKit's recent switch away from LLVM</a>)</p>
<br>
<p class="fragment"><b>Incremental compilation</b> will eventually help make compile time matter less</p>
<br>
<p class="fragment">But it still does, in particular <b>LTO-type builds</b> which matter a lot on the web</p>
<br>
<p class="fragment"><strong>Power of LLVM codegen comes at a cost</strong></p>
</section>
<section>
<p>For C++, you <b>may be using clang+LLVM anyhow</b>, so wasm backend is a natural fit</p>
<br>
<p class="fragment">But if we focus now on other languages, <strong>options may be more open</strong></p>
</section>
<section>
<p>One option is to <b>use Binaryen as a compiler backend</b>, without LLVM or something else:
<br>
<br>
<p style="background-color: black; padding: 0.4em; box-shadow: 8px 8px 8px rgba(0,0,0,0.6)"><b style="color: #4f2">your compiler</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #68f">binaryen</b><b style="color: #fff">&nbsp&nbsp&rArr;</b>&nbsp&nbsp<b style="color: #f42">wasm</b></p>
<br>
<p class="fragment">Let's see some of the benefits of doing this</p>
</section>
<section>
<p>Binaryen can handle wasm-specific tasks (emit the binary format, minification, etc.) <b>and</b> general optimization</p>
<br>
<div class="fragment">
<p>If you want a compiler backend that optimizes <strong>and</strong> emits wasm, Binaryen can do all that</p>
<br>
<p>And then your compiler might not need another dependency</p>
</div>
</section>
<!- -section>
<p>Binaryen's IR is <b>simpler</b> than LLVM's</p>
<br>
<p>E.g. no arbitrary-sized ints, no irreducible control flow</p>
<br>
<p class="fragment">Limits some optimizations, but passes run faster</p>
</section- ->
<!- -section>
<p>In fact <b>Binaryen's IR is basically WebAssembly itself</b></p>
<br>
<p class="fragment">Optimize and emit wasm using a single IR: avoid the overhead of constructing and translating between multiple IRs</p>
<br>
<p class="fragment">When this is good enough, it can be very fast</p>
<br>
<p class="fragment">May need to change this eventually; let's see how far we can get without it</p>
</section- ->
<section>
<p><strong>Speed</strong>: Binaryen has <b>minimal, compact data structures</b></p>
<br>
<p>E.g., no parent/context pointers</p>
<br>
<p>Cache-friendly, <b>fast to traverse</b></p>
<br>
<p class="fragment">Less general optimization framework than LLVM, and in some cases things need to be recomputed (use lists)</p>
<br>
<p class="fragment">But tradeoff often worth it (similar philosophy to the <a href="https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/">B3 JIT</a>)</p>
</section>
<section>
<p>LLVM is single-threaded</p>
<br>
<p class="fragment">Binaryen can both <b>build IR, and optimize it, using multiple cores</b></p>
<br>
<p class="fragment">Can also <strong>pipeline</strong>: optimize ready functions while others are still being generated</p>
<br>
<p class="fragment">Binaryen functions do not refer to global state, making this straightforward</p>
</section>
<! --section>
<p>Binaryen only compiles to WebAssembly, and <b>WebAssembly is very simple</b> compared to x86, ARM, etc.</p>
<br>
<p>WebAssembly is like an abstracted RISC-like arch &rArr; <b>instruction selection is simple</b></p>
<br>
<p class="fragment">No need for register allocation, scheduling, etc. - WebAssembly <strong>VMs</strong> do that!</p>
<br>
<p class="fragment">As a result, some of LLVM's power is <b>irrelevant anyhow</b></p>
</section- ->
<section>
<p>Binaryen is <b>much smaller</b> than LLVM</p>
<br>
<p>If you need all of LLVM's power, definitely worth it, but you don't always</p>
</section>
-->
<section>
<h3>Measurements on BananaBread</h3>
<a href="https://kripken.github.io/BananaBread/wasm-demo/index.html"><img src="bananabread.jpg"></img></a>
<p>Port of <a href="http://sauerbraten.org/">Cube 2/Sauerbraten</a> to the Web</p>
<p>Interesting <b>real-world codebase</b>, medium size game engine</p>
</section>
<section>
<p>Binaryen on <strong>unoptimized</strong> asm.js (straight from asm.js backend):</p>
<br>
<center>
<table>
<tr><td style="padding: 0.25em"><b>binaryen opts</b></td><td style="text-align: center"><b>no</b></td><td style="text-align: center"><b>yes</b></td><td style="padding: 0.25em"></td><td style="padding: 0.25em"></td></tr>
<tr><td colspan=4><hr></td></tr>
<tr><td style="padding: 0.25em">binary size (MB)</td><td style="padding: 0.25em">3.80</td><td style="padding: 0.25em">2.46</td><td style="padding: 0.25em"><strong>-35%</strong></td></tr>
<tr><td style="padding: 0.25em">time (seconds)</td><td style="padding: 0.25em">2.98</td><td style="padding: 0.25em">3.60</td><td style="padding: 0.25em"></td></tr>
</table>
</center>
<p><small>(less is better on all)</small></p>
<br>
<p class="fragment">Binaryen's general and wasm-specific optimizations can optimize the code <b>quite a lot</b></p>
<br>
<p class="fragment">Note wall time increases by just 21%</p>
</section>
<section>
<center>
<p>Binaryen on <strong>optimized</strong> asm.js (using emscripten's asm.js optimizer):</p>
<br>
<table>
<tr><td style="padding: 0.25em"><b>binaryen opts</b></td><td style="text-align: center"><b>no</b></td><td style="text-align: center"><b>yes</b></td><td style="padding: 0.25em"></td><td style="padding: 0.25em"></td></tr>
<tr><td colspan=4><hr></td></tr>
<tr><td style="padding: 0.25em">binary size (MB)</td><td style="padding: 0.25em">2.44</td><td style="padding: 0.25em">2.16</td><td style="padding: 0.25em"><strong>-13%</strong></td></tr>
<tr><td style="padding: 0.25em">time (seconds)</td><td style="padding: 0.25em">1.63</td><td style="padding: 0.25em">2.13</td><td style="padding: 0.25em"></td></tr>
</table>
</center>
<br>
<p class="fragment">Less of a benefit since code is already fairly optimized, but <b>still significant</b></p>
<br>
<p class="fragment">wasm-specific optimization matters, <b>general optimizations are not enough</b></p>
</section>
<section>
<p>Binaryen is also <strong>fast</strong></p>
<br>
<div class="fragment">
<p><b>Minimal, compact data structures</b></p>
<br>
<p>E.g., no parent/context pointers; cache-friendly, <b>fast to traverse</b></p>
<br>
</div>
<p class="fragment">Less general optimization framework than e.g. LLVM, and in some cases things need to be recomputed (use lists)</p>
<br>
<p class="fragment">But tradeoff often worth it (similar philosophy to the <a href="https://webkit.org/blog/5852/introducing-the-b3-jit-compiler/">B3 JIT</a> which replaced LLVM in WebKit)</p>
</section>
<section>
<p><strong>Speed part 2</strong>: parallelism</p>
<br>
<p class="fragment">LLVM is single-threaded</p>
<br>
<p class="fragment">Binaryen can both <b>build IR, and optimize it, using multiple cores</b></p>
<br>
<p class="fragment">Can also <strong>pipeline</strong>: optimize ready functions while others are still being generated</p>
<!--br>
<p class="fragment">Binaryen functions do not refer to global state, making this straightforward</p-->
</section>
<section>
<p>In some cases might be worth <b>using Binaryen as a full compiler backend</b>, without LLVM or something else:
<br>
<br>
<p style="background-color: black; padding: 0.4em; box-shadow: 8px 8px 8px rgba(0,0,0,0.6)"><b style="color: #f54">compiler</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #f86">Binaryen</b><b style="color: #fff">&nbsp&nbsp&rArr;</b>&nbsp&nbsp<b style="color: #ff8">wasm</b></p>
<br>
<p>Binaryen optimizes <b>and</b> emits wasm, and does so very quickly</p>
</section>
<!--section>
<center>
<p>Can also run Binaryen on wasm from the <b>wasm backend</b>:</p>
<br>
<table>
<tr><td style="padding: 0.25em"><b>binaryen opts</b></td><td style="padding: 0.25em"><b>no</b></td><td style="padding: 0.25em"><b>yes</b></td><td style="padding: 0.25em"></td><td style="padding: 0.25em"></td></tr>
<tr><td style="padding: 0.25em">binary size (MB)</td><td style="padding: 0.25em">2.10</td><td style="padding: 0.25em">2.05</td><td style="padding: 0.25em"><strong>-2.5%</strong></td></tr>
</table>
</center>
<br>
<p class="fragment">LLVM has excellent general optimizations, as well as wasm-specific ones like coloring and stackification, but a small improvement is still possible</p>
</section-->
<!--section>
<p>An important takeaway from these numbers is that to emit efficient wasm you need to <b>optimize</b> it</p>
<br>
<p>Just like you minify JS or CSS, basically</p>
</section-->
<!--section>
<h3>Using Binaryen</h3>
<br>
<p>Binaryen aims to be <a href="https://github.com/WebAssembly/binaryen/wiki/Compiling-to-WebAssembly-with-Binaryen">simple to use</a></p>
<br>
<p class="fragment">Straightforward <a href="https://github.com/WebAssembly/binaryen/wiki/Compiling-to-WebAssembly-with-Binaryen#c-api-1">C API</a> in one header; can also use C++</p>
<br>
<p class="fragment">Input can be <strong>structured</strong> (loops, ifs), also an API for <strong>general control flow graphs</strong> (which we "reloop")</p>
<br>
<p class="fragment">Input in <strong>register form</strong>; ok if there are tons of locals (e.g., from SSA), we optimize that down</p>
</section-->
<section>
<h3>Rust + Binaryen</h3>
<p><a href="https://github.com/brson/mir2wasm/">https://github.com/<b>brson</b>/<strong>mir2wasm</strong></a></p>
<br>
<p style="background-color: black; padding: 0.4em; box-shadow: 8px 8px 8px rgba(0,0,0,0.6)"><b style="color: #f54">Rust</b>&nbsp&nbsp<b style="color: #fff">&rArr;&nbsp&nbsp</b><b style="color: #f86">Rust MIR</b>&nbsp&nbsp<b style="color: #fff">&rArr;</b>&nbsp&nbsp<b style="color: #fb7">Binaryen</b><b style="color: #fff">&nbsp&nbsp&rArr;</b>&nbsp&nbsp<b style="color: #ff8">wasm</b></p>
<br>
<p class="fragment">Very early stage, can emit some numerical operations</p>
<br>
<p class="fragment">Expect to have very good codegen times</p>
<br>
<p class="fragment">Help is welcome!</p>
</section>
<section>
<h2>Summary</h2>
<br>
<p><b><a href="https://github.com/WebAssembly/binaryen">https://github.com/WebAssembly/binaryen</a></b></p>
<br>
<p>Binaryen aims to be a <b>flexible, fast, and easy to use</b> way for compilers to target WebAssembly</p>
<br>
<p class="fragment"><b>Let's get more code on the web!</b></p>
<br>
<div class="fragment">
<hr>
<br>
<p><strong>That's it, thank you for listening :)</strong></p>
</div>
</section>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: 'beige', //Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'linear', // default/cube/page/concave/zoom/linear/fade/none
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
// { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
</div>
</div>
</body>
</html>
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors_kripken/talks.git
git@gitee.com:mirrors_kripken/talks.git
mirrors_kripken
talks
talks
master

搜索帮助