📄 Page
1
(This page has no text content)
📄 Page
2
Practical WebAssembly Explore the fundamentals of WebAssembly programming using Rust Sendil Kumar Nellaiyapen BIRMINGHAM—MUMBAI
📄 Page
3
Practical WebAssembly Copyright © 2022 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information. Associate Group Product Manager: Pavan Ramchandani Publishing Product Manager: Bhavya Rao Senior Editor: Mark Dsouza Content Development Editor: Divya Vijayan Technical Editor: Joseph Aloocaran Copy Editor: Safis Editing Project Coordinator: Rashika Ba Proofreader: Safis Editing Indexer: Subalakshmi Govindhan Production Designer: Alishon Mendonca Marketing Coordinator: Anamika Singh First published: April 2022 Production reference: 1290422 Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK. ISBN 978-1-83882-800-4 www.packt.com
📄 Page
4
To all the amazing developers out there.
📄 Page
5
Contributors About the author Sendil Kumar Nellaiyapen is an engineering manager building web payments at Uber. He is passionate about the web and cloud technologies. He has over 12 years of experience in building distributed, cloud-native, and enterprise systems. He occasionally rambles on his website and speaks at various conferences. He is an active open source contributor and enjoys building communities. He loves to learn and explore new programming languages. I want to thank the amazing Rust and web community.
📄 Page
6
About the reviewer Sufyan bin Uzayr is a writer, teacher, and developer with 10+ years of experience in the industry. He is an open source enthusiast and specializes in a wide variety of technologies. He holds four master's degrees and has authored multiple books. Sufyan is an avid writer. He regularly writes about topics related to coding, tech, politics, and sports. He is a regular columnist for various publications and magazines. Sufyan is the CEO of Parakozm, a software development company catering to a global clientele. He is also the CTO at Samurai Servers, a web server management company focusing mainly on enterprise-scale audiences. In his spare time, Sufyan teaches coding and English to young students. Learn more about his works at https://sufyanism.com/.
📄 Page
7
(This page has no text content)
📄 Page
8
Preface Section 1: Introduction to WebAssembly 1 Understanding LLVM Technical requirements 4 Understanding compilers 4 Compiled languages 5 Compiler efficiency 6 Exploring LLVM 7 LLVM in action 8 Summary 10 2 Understanding Emscripten Technical requirements 13 Installing Emscripten using emsdk 13 Generating asm.js using Emscripten 15 Running Hello World with Emscripten in Node.js 17 Running Hello World with Emscripten in the browser 20 Exploring other options in emsdk 22 Listing the tools and SDK 24 Managing the tools and SDK 25 Understanding various levels of optimizations 28 Optimizations 28 Closure Compiler 32 Summary 34 Table of Contents
📄 Page
9
viii Table of Contents 3 Exploring WebAssembly Modules Technical requirements 36 Understanding how WebAssembly works 36 Understanding JavaScript execution inside the JavaScript engine 36 Understanding WebAssembly execution inside the JavaScript engine 38 Exploring the WebAssembly text format 40 Building a function in WebAssembly text format 45 Summary 50 Section 2: WebAssembly Tools 4 Understanding WebAssembly Binary Toolkit Technical requirements 54 Getting started with WABT 54 Installing WABT 54 Converting WAST into WASM 58 Converting WASM into WAST 62 -f or --fold-exprs 66 Converting WASM into C 67 simple.h 68 simple.c 69 Converting WAST into JSON 73 Understanding a few other tools provided by WABT 75 wasm-objdump 75 wasm-strip 78 wasm-validate 79 wasm-interp 81 Summary 82 5 Understanding Sections in WebAssembly Modules Technical requirements 84 Exports and imports 84 Exports 84 Imports 87 Globals 89 Start 95 Memory 96 Summary 100
📄 Page
10
Table of Contents ix 6 Installing and Using Binaryen Technical requirements 102 Installing and using Binaryen 102 Linux/macOS 103 Windows 103 wasm-as 105 wasm-dis 107 wasm-opt 109 wasm2js 111 Summary 113 Section 3: Rust and WebAssembly 7 Integrating Rust with WebAssembly Technical requirements 118 Installing Rust 118 Converting Rust into WebAssembly via rustc 120 Converting Rust into WebAssembly via Cargo 123 Installing wasm-bindgen 127 Converting Rust into WebAssembly via wasm-bindgen 129 Summary 135 8 Bundling WebAssembly Using wasm-pack Technical requirements 138 Bundling WebAssembly modules with webpack 138 Bundling WebAssembly modules with Parcel 145 Introducing wasm-pack 150 Why do you need wasm-pack? 150 How to use wasm-pack 150 Packing and publishing using wasm-pack 153 Summary 157
📄 Page
11
x Table of Contents 9 Crossing the Boundary between Rust and WebAssembly Technical requirements 160 Sharing classes from Rust with JavaScript 160 Sharing classes from JavaScript with Rust 164 Calling the JavaScript API via WebAssembly 169 Calling closures via WebAssembly 173 Importing the JavaScript function into Rust 177 Calling a web API via WebAssembly 180 Summary 185 10 Optimizing Rust and WebAssembly Technical requirements 187 Minimizing the WebAssembly modules 188 Analyzing the memory model in the WebAssembly module 192 Sharing memory between JavaScript and WebAssembly using Rust 192 Creating a memory object in JavaScript to use in the Rust application 195 Analyzing the WebAssembly module with Twiggy 198 top 200 monos 202 garbage 203 Summary 204 Index Other Books You May Enjoy
📄 Page
12
Preface Delivering high-performance applications is a nightmare. JavaScript is a dynamically typed language. Thus, the JavaScript engine assumes the type when executing JavaScript. These assumptions lead to unpredictable performance. This makes it even harder to deliver consistently high-performance applications in JavaScript. WebAssembly provides a way to run type-safe and high-performance applications in the JavaScript engine. WebAssembly is blazingly fast WebAssembly is the next great thing that happened in the web. It promises high and consistent performance with maintainable code, running native code and providing near- native performance on the web. WebAssembly is type-safe The JavaScript compiler struggles to provide high performance when you have polymorphic JavaScript code. WebAssembly, on the other hand, is type-safe (or monomorphic) at compile time. This not only boosts performance but also greatly reduces runtime errors, which is a win-win. WebAssembly runs your native code There have been multiple attempts to make the web faster by running native code. But they all failed because they are either vendor-specific or tied to a single language. The web is built on top of open standards. By being an open standard, WebAssembly makes it easy for all companies to adopt and support it. WebAssembly is not a language; it is a high-level implementation plan for other languages that compile to byte code that will run on the JavaScript engines.
📄 Page
13
xii Preface WebAssembly is byte code WebAssembly is nothing but a bytecode that runs in JavaScript Engine. In this book, we will learn how to convert native code into WebAssembly and how to optimize it to get even better performance. We will also cover how the entire WebAssembly runs on the JavaScript engine and how to use the various tools available and what they help us to achieve. Most importantly, learn where and how to use WebAssembly to get the desired result out of it. Let's make the web even more awesome and faster with WebAssembly. Who this book is for This book is for JavaScript developers who want to deliver better performance and ship type-safe code. Rust developers or backend engineers looking to build full-stack applications without worrying too much about JavaScript programming will also find the book useful. A basic understanding of JavaScript is required to follow along with this book. Rust knowledge is preferred but not mandatory. The code samples are simple and easy for any developer to follow along with. What this book covers Chapter 1, Understanding LLVM, gives a brief introduction to LLVM, what it is, and how to use it. Chapter 2, Understanding Emscripten, introduces you to Emscripten, where you will build and run your first WebAssembly module. Chapter 3, Exploring WebAssembly Modules, explores the WebAssembly module, what the module consists of, and what the different sections are. Chapter 4, Understanding WebAssembly Binary Toolkit, explores how to install and use WebAssembly Binary Toolkit (WABT). Chapter 5, Understanding Sections in WebAssembly Modules, explores various sections inside the WebAssembly binary and what their purpose is. Chapter 6, Installing and Using Binaryen, explores how to install and use Binaryen.
📄 Page
14
Preface xiii Chapter 7, Integrating Rust with WebAssembly, starts by looking at Rust and various ways to convert Rust into a WebAssembly module and ends by looking at wasm_bindgen. Chapter 8, Bundling WebAssembly Using wasm-pack, explores wasm-pack and how it makes it easy to build Rust and WebAssembly applications. Chapter 9, Crossing the Boundary between Rust and WebAssembly, focuses on how wasm- bindgen, along with crates such as js-sys and web-sys, helps to share entities from WebAssembly with JavaScript. Chapter 10, Optimizing Rust and WebAssembly, introduces various ways to optimize Rust and WebAssembly with examples. To get the most out of this book The book assumes that you have a basic understanding of JavaScript. The code samples are mostly written in C++/Rust. Please install Rust (briefly explained in Chapter 7, Integrating Rust with WebAssembly) and Node.js before starting. If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book's GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code. Download the example code files You can download the example code files for this book from GitHub at https:// github.com/PacktPublishing/Practical-WebAssembly. If there's an update to the code, it will be updated in the GitHub repository. We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
📄 Page
15
xiv Preface Conventions used There are a number of text conventions used throughout this book. Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "Mount the downloaded WebStorm-10*.dmg disk image file as another disk in your system." A block of code is set as follows: html, body, #map { height: 100%; margin: 0; padding: 0 } When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold: [default] exten => s,1,Dial(Zap/1|30) exten => s,2,Voicemail(u100) exten => s,102,Voicemail(b100) exten => i,1,Voicemail(s0) Any command-line input or output is written as follows: $ mkdir css $ cd css Bold: Indicates a new term, an important word, or words that you see onscreen. For instance, words in menus or dialog boxes appear in bold. Here is an example: "Select System info from the Administration panel." Tips or Important Notes Appear like this.
📄 Page
16
Preface xv Get in touch Feedback from our readers is always welcome. General feedback: If you have questions about any aspect of this book, email us at customercare@packtpub.com and mention the book title in the subject of your message. Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata and fill in the form. Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at copyright@packt.com with a link to the material. If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors. packtpub.com. Share Your Thoughts Once you've read Practical WebAssembly, we'd love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback. Your review is important to us and the tech community and will help us make sure we're delivering excellent quality content.
📄 Page
17
(This page has no text content)
📄 Page
18
This section gives a brief introduction to LLVM and Emscripten. You will learn what they are and why you need to understand them before learning about WebAssembly. This section ends with an introduction to the WebAssembly module and WebAssembly text format. You will understand what WebAssembly is and how it works after this section. This section comprises the following chapters: • Chapter 1, Understanding LLVM • Chapter 2, Understanding Emscripten • Chapter 3, Exploring WebAssembly Modules Section 1: Introduction to WebAssembly
📄 Page
19
(This page has no text content)
📄 Page
20
1 Understanding LLVM JavaScript is one of the most popular programming languages. However, JavaScript has two main disadvantages: • Unpredictable performance JavaScript executes inside the environment and runtime provided by JavaScript engines. There are various JavaScript engines (V8, WebKit, and Gecko). All of them were built differently and run the same JavaScript code in a different way. Added to that, JavaScript is dynamically typed. This means JavaScript engines should guess the type while executing the JavaScript code. These factors lead to unpredictable performance in JavaScript execution. The optimizations for one type of JavaScript engine may cause undesirable side effects on other types of JavaScript engines. This leads to unpredictable performance. • Bundle size The JavaScript engine waits until it downloads the entire JavaScript file before parsing and executing. The larger the JavaScript file, the longer the wait will be. This will degrade your application's performance. Bundlers such as webpack help to minimize the bundle size. But when your application grows, the bundle size grows exponentially. Is there a tool that provides native performance and comes in a much smaller size? Yes, WebAssembly.