Pro Yearly is on sale from $80 to $50! »

WebAssembly from the Java Perspective

WebAssembly from the Java Perspective

An introduction to WebAssembly and ho to build it from Java and Kotlin.

50ac0c865b08c39a764842605f2bc6df?s=128

Dmitry Alexandrov

November 23, 2019
Tweet

Transcript

  1. WebАssembly from Java Perspective

  2. Dmitry Aleksandrov Chief Architect | JUG co-lead | Java Champion

  3. None
  4. None
  5. Back to Java-Applets?

  6. Disclaimer: We have to first understand what WebAssembly is than

    see how to use it with Java
  7. Disclaimer: (Keep It Simple and Stupid)

  8. None
  9. None
  10. Modern Web

  11. None
  12. None
  13. HTML:

  14. CSS: Sorry, no funny image found...

  15. JavaScript: JavaScript (/ˈdʒɑːvəˌskrɪpt/), often abbreviated as JS, is a high-level,

    interpreted programming language that conforms to the ECMAScript specification. It is a language that is also characterized as dynamic, weakly typed, prototype-based and multi-paradigm. Created 04 December 1995 by Brendan Eich. © Wikipedia
  16. Once this was just enough

  17. None
  18. None
  19. And all those frameworks...

  20. But now:

  21. None
  22. What is this? Compiling for the Web with WebAssembly (Google

    I/O '17)
  23. You will be surprised...: Compiling for the Web with WebAssembly

    (Google I/O '17) function add(a, b) { return a + b }
  24. V8 - JS Compiling for the Web with WebAssembly (Google

    I/O '17)
  25. None
  26. There were many attempts to optimize:

  27. There were many attempts to optimize: Compiling for the Web

    with WebAssembly (Google I/O '17)
  28. Even games!

  29. V8 - JS Compiling for the Web with WebAssembly (Google

    I/O '17)
  30. We need a lot of Performance!!!

  31. We need it in SMALL devices!!!

  32. None
  33. And in 2015 came WebAssembly!

  34. JS!

  35. None
  36. What is WebAssembly WebAssembly (abbreviated Wasm) is a binary instruction

    format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust/Java/Python, enabling deployment on the web for client and server applications. © Wikipedia
  37. Virtual Architecture https://hacks.mozilla.org/2017/02/a-crash-course-in-assembly/

  38. What is WebАssembly The kind of binary format being considered

    for WebAssembly can be natively decoded much faster than JavaScript can be parsed (experiments show more than 20× faster). On mobile, large compiled codes can easily take 20–40 seconds just to parse, so native decoding (especially when combined with other techniques like streaming for better-than-gzip compression) is critical to providing a good cold- load user experience. from the FAQ of WebAssembly
  39. What is WebAssembly Efficient and fast The Wasm stack machine

    is designed to be encoded in a size- and load-time- efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms.
  40. What is WebAssembly Efficient and fast The Wasm stack machine

    is designed to be encoded in a size- and load-time- efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms. Safe WebAssembly describes a memory-safe, sandboxed execution environmentthat may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same- origin and permissions security policies of the browser.
  41. What is WebAssembly Efficient and fast The Wasm stack machine

    is designed to be encoded in a size- and load-time- efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms. Safe WebAssembly describes a memory-safe, sandboxed execution environment that may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same- origin and permissions security policies of the browser. Open and debuggable WebAssembly is designed to be pretty-printedin a textual format for debugging, testing, experimenting, optimizing, learning, teaching, and writing programs by hand. The textual format will be used when viewing the source of Wasm modules on the web.
  42. What is WebAssembly Efficient and fast The Wasm stack machine

    is designed to be encoded in a size- and load-time- efficient binary format. WebAssembly aims to execute at native speed by taking advantage of common hardware capabilities available on a wide range of platforms. Safe WebAssembly describes a memory-safe, sandboxed execution environment that may even be implemented inside existing JavaScript virtual machines. When embedded in the web, WebAssembly will enforce the same- origin and permissions security policies of the browser. Open and debuggable WebAssembly is designed to be pretty-printed in a textual format for debugging, testing, experimenting, optimizing, learning, teaching, and writing programs by hand. The textual format will be used when viewing the source of Wasm modules on the web. Part of the open web platform WebAssembly is designed to maintain the versionless, feature-tested, and backwards-compatible nature of the web. WebAssembly modules will be able to call into and out of the JavaScript context and access browser functionality through the same Web APIs accessible from JavaScript. WebAssembly also supports non-webembeddings.
  43. Its very very fresh • April 2015 - WebAssembly Community

    Group started • June 2015 - The first public announcement • March 2016 - Definition of core feature with multiple interoperable implementations • October 2016 - Browser Preview announced with multiple interoperable implementations • February 2017 - Official logo chosen • March 2017 - Cross-browser consensus and end of Browser Preview
  44. It is shipped with:

  45. It is shipped with:

  46. In the greater scheme of things, the arrival of WebAssembly

    means that you will not be forced anymore to use JavaScript for the web, because it is the only thing that run in the browser!
  47. None
  48. WebAssembly is NOT a replacement for HTML/JavaScript

  49. WebAssembly is PART of the infrastructure...

  50. None
  51. V8 - WebAssembly Compiling for the Web with WebAssembly (Google

    I/O '17)
  52. V8 - WebAssembly Compiling for the Web with WebAssembly (Google

    I/O '17)
  53. What is it? Compiling for the Web with WebAssembly (Google

    I/O '17)
  54. WebAssembly binary code Compiling for the Web with WebAssembly (Google

    I/O '17)
  55. WebAssembly language Compiling for the Web with WebAssembly (Google I/O

    '17)
  56. Current WebAssembly runs at 1.2x true native!

  57. So, how can we use WebAssembly?

  58. Disclaimer: we’ll now get low level.

  59. The founding principle ... is to integrate well with the

    existing JavaScript world.
  60. The founding principle ... is to integrate well with the

    existing JavaScript world. This ranges from technical things, such as interoperability and sharing the security policies (same-origin),
  61. The founding principle ... is to integrate well with the

    existing JavaScript world. This ranges from technical things, such as interoperability and sharing the security policies (same-origin), to tooling integration, such as as supporting the View Source functionality of web browsers.
  62. The founding principle Both Binary

  63. The founding principle Both Binary ... and text format:

  64. Ref: https://tomassetti.me/introduction-to-webassembly/

  65. Why C??

  66. Why C??

  67. Why C?? • Objective of the initial release (MVP)

  68. Why C?? • Objective of the initial release (MVP) •

    MVP is not Most Valuable Professional
  69. Why C?? • Objective of the initial release (MVP) •

    MVP is not Most Valuable Professional • MVP is Minimal Viable Product
  70. Why C?? • Objective of the initial release (MVP) •

    MVP is not Most Valuable Professional • MVP is Minimal Viable Product • The MVP of WebAssembly does not support garbage collection
  71. Why C?? • Objective of the initial release (MVP) •

    MVP is not Most Valuable Professional • MVP is Minimal Viable Product • The MVP of WebAssembly does not support garbage collection • Rely on LLVM (one of the most used set of compiler tools)
  72. MVP Feature Tracking issue Status Phase Specification 1077 in progress

    Proposed spec text available Threads 1073 in progress Feature proposal Fixed-width SIMD 1075 in progress Feature proposal Exception handling 1078 in progress Feature proposal Garbage collection 1079 in progress Feature proposal Bulk memory operations 1114 in progress Feature proposal Web Content Security Policy 1122 in progress Pre-proposal ECMAScript module integration 1087 in progress Feature proposal Tail Call 1144 in progress Feature proposal Non-trapping float-to-int conversions 1143 in progress Implementation phase Multi-value 1146 in progress Implementation phase Host bindings 1148 in progress Feature proposal Sign-extension operators 1178 in progress Implementation phase Import/Export Mutable Globals 1179 in progress Implementation phase Type Reflection for WebAssembly JavaScript API 1181 in progress Feature proposal Unmanaged closures 1182 in progress Feature proposal JavaScript BigInt to WebAssembly i64 integration 1186 in progress Proposed Spec Text Available Custom Annotation Syntax in the Text Format 1192 in progress Feature proposal
  73. Enough theory!

  74. Hello, world! •Infrastructure: •Emscripten •WebAssembly Binary Toolkit •Binaryen

  75. Hello, world! #include <stdio.h> int main() { printf("Hello, world!"); return

    0; }
  76. Hello, world! ╭─buzz@buzz.local ~/Webassembly/Example1 ╰─➤ emcc hello.c -s WASM=1 -o

    hello.html
  77. Hello, world! ╭─buzz@buzz.local ~/Webassembly/Example1 ╰─➤ emcc hello.c -s WASM=1 -o

    hello.html
  78. Hello, world!

  79. As you see, WebAssembly does not cancel HTML/JavaScript

  80. Wasm Engine actually lives inside JS engine,

  81. ... so they can talk to each other natively

  82. External calls: step 1 – the code (C) extern int

    print_value(int x); void call_func(int input) { print_value(input * 3); }
  83. External calls: step 2 – interop (JS) if ('WebAssembly' in

    window) { var importObj = { env: { _print_value: x => document.getElementById('wasm').innerHTML = 'Value:' + x } }; WebAssembly.instantiateStreaming(fetch('call_func.wasm'), importObj).then(result => result.instance.exports._call_func(9)); }
  84. External calls: step 3 – all together (HTML) <html> <head>

    <meta charset='UTF-8'> <script src="output.js"></script> </head> <body> <label id='wasm'></label> </body> </html>
  85. And move data back> and <forth

  86. Since we are low level • Only binary data can

    be moved
  87. Since we are low level • Only binary data can

    be moved • The data is moved in chunks called pages
  88. Since we are low level • Only binary data can

    be moved • The data is moved in chunks called pages • Each page is 64K
  89. Since we are low level • Only binary data can

    be moved • The data is moved in chunks called pages • Each page is 64K • Memory access is done via offsets
  90. Moving data: step 1 – the code (C) #define NUM_VALS

    8 int input_array[NUM_VALS]; int scalar_add() { int product = 0; for(int i=0; i<NUM_VALS; i++) { product += input_array[i]; } return product; } int* getInputArrayOffset() { return &input_array[0]; }
  91. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  92. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  93. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  94. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  95. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  96. Moving data: step 2 – interop (JS) if ('WebAssembly' in

    window) { // Add memory object to the import object var memObj = new WebAssembly.Memory({initial: 256, maximum: 256}); var importObj = { env: { memory: memObj} }; // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('scalarAdd.wasm'), importObj) .then(result => { // Get the addresses of the input array offset = result.instance.exports._getInputArrayOffset(); // Create and initialize array var inputArray = new Uint32Array(memObj.buffer, offset, 8); inputArray.fill(6); // Compute the product product = result.instance.exports._scalar_add(); document.getElementById('wasm').innerHTML = 'Scalar add product: ' + product; }); }
  97. Moving data: step 3 – all together (HTML) <html> <head>

    <meta charset='UTF-8'> <script src="output.js"></script> </head> <body> <label id='wasm'></label> </body> </html>
  98. Cool! It works on your machine!

  99. What about debugging?

  100. Hello, world! ╭─buzz@buzz.local ~/Webassembly/Example1 ╰─➤ emcc hello.c -s -g WASM=1

    -o hello.html
  101. Hello, world! ╭─buzz@buzz.local ~/Webassembly/Example1 ╰─➤ emcc hello.c -s -g WASM=1

    -o hello.html
  102. ... there are also other options: • -g4 and –source-map-base

    http://localhost:8080/ • emcc add.c -O1 -g4 -s WASM=1 -s SIDE_MODULE=1 -s EXPORTED_FUNCTIONS='["_add"]' -o add.wasm --source-map-base http://localhost:8080/ *http://webassemblycode.com/using-browsers-debug-webassembly/
  103. Oh, that’s boring!

  104. Give me

  105. Currently there are: •JWebAssembly

  106. Currently there are: •JWebAssembly •TeaVM

  107. JWebAssembly: Java public class Add { @Export public static int

    add( int a, int b ) { return a + b; } }
  108. JWebAssembly: Java public static void main(String[] args) throws Exception {

    JWebAssembly webAsm = new JWebAssembly(); webAsm.addFile(new File(”<..>/Add.class")); String text = webAsm.compileToText(); System.out.println(text); }
  109. JWebAssembly: Output (module (export "add" (func $local/samples/mitia/Add.add)) (func $local/samples/mitia/Add.add (param

    i32) (param i32) (result i32) get_local 0 get_local 1 i32.add return ) )
  110. TeaVM https://binji.github.io/gotosthlm-talk/#/25

  111. TeaVM: Step 1 – setup (Maven) ... <dependency> <groupId>org.teavm</groupId> <artifactId>teavm-classlib</artifactId>

    <version>${project.version}</version> </dependency> <dependency> <groupId>org.teavm</groupId> <artifactId>teavm-jso-apis</artifactId> <version>${project.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.teavm</groupId> <artifactId>teavm-interop</artifactId> <version>${project.version}</version> </dependency> ...
  112. TeaVM: Step 2 – the code (Java) public class WasmFunctions

    { @Export(name = "thePurposeOfLife") public static int getThePurposeOfLife(){ return 43; } public static void main(String[] args) { } }
  113. TeaVM: Step 3 – compile to Wasm (Maven) <plugin> <artifactId>maven-war-plugin</artifactId>

    <version>2.4</version> <configuration> <webResources> <resource> <directory>${project.build.directory}/generated/wasm</directory> </resource> </webResources> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin>
  114. TeaVM: Step 4 – compile to Wasm (Maven) <plugin> <groupId>org.teavm</groupId>

    <artifactId>teavm-maven-plugin</artifactId> <version>${project.version}</version> <executions> <execution> <id>wasm-client</id> <goals> <goal>compile</goal> </goals> <configuration> <targetDirectory>${project.build.directory}/generated/wasm/wasm</targetDirectory> <mainClass>local.mitia.wasm.WasmFunctions</mainClass> <debugInformationGenerated>true</debugInformationGenerated> <targetType>WEBASSEMBLY</targetType> <optimizationLevel>FULL</optimizationLevel> <heapSize>8</heapSize> </configuration> </execution> </executions> </plugin>
  115. TeaVM: Step 5 – all together (JS/HTML) JS: if ('WebAssembly'

    in window) { // Set the import object in instantiateStreaming WebAssembly.instantiateStreaming(fetch('wasm /classes.wasm')) .then(result => { //the Purpse of Life is: result = result.instance.exports.thePurposeOfLife(); document.getElementById('wasm').innerHTML = 'The Purpose of life according to teavm wasm from java: ' + result; }); } HTML: <html> <head> <meta charset='UTF-8'> <script src="output.js"></script> </head> <body> <label id='wasm'></label> </body> </html>
  116. Demo time

  117. What about ?

  118. What about ?

  119. s

  120. Kotlin way: Kotlin as a JVM Language

  121. Kotlin way: Kotlin as a JVM Language Kotlin/Native

  122. Kotlin way: Kotlin as a JVM Language Kotlin/Native LLVM

  123. Kotlin way: Kotlin as a JVM Language Kotlin/Native LLVM WebAssembly

  124. Kotlin way: Kotlin as a JVM Language Kotlin/Native LLVM WebAssembly

  125. Kotlin way: step 1 – the code (kt) import kotlinx.interop.wasm.dom.*

    import kotlinx.wasm.jsinterop.* fun main(args: Array<String>) { println("Hello Kotlin/Native!") }
  126. Kotlin way: step 2 – the build (gradle) buildscript {

    repositories { jcenter() maven { url "http://kotlin.bintray.com/kotlinx" } maven { url "https://plugins.gradle.org/m2/" } maven { url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version" classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version" } } apply plugin: 'konan' konanArtifacts { program('wasmFunctions', targets: ['wasm32']) { srcDir 'src/main/kotlin' libraries { useRepo 'lib' klib 'dom' } } }
  127. Kotlin way: step 2 – the build (gradle) buildscript {

    repositories { jcenter() maven { url "http://kotlin.bintray.com/kotlinx" } maven { url "https://plugins.gradle.org/m2/" } maven { url "https://dl.bintray.com/jetbrains/kotlin-native-dependencies" } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version" classpath "org.jetbrains.kotlin:kotlin-native-gradle-plugin:$kotlin_native_version" } } apply plugin: 'konan' konanArtifacts { program('wasmFunctions', targets: ['wasm32']) { srcDir 'src/main/kotlin' libraries { useRepo 'lib' klib 'dom' } } }
  128. None
  129. Competitors?

  130. C# https://www.slideshare.net/sweko/blazor-c-for-the-web

  131. Rust https://rustwasm.github.io/book/

  132. Go https://github.com/golang/go/wiki/WebAssembly

  133. WASI https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/

  134. None
  135. None
  136. Bloody enterprise

  137. Real world: 0 500 1000 1500 2000 2500 JS Asm.js

    Wasm Sorting 10k entries Sorting 10k entries
  138. None
  139. Isn’t it already outdated?

  140. Or not even born?

  141. Their main problem is:

  142. Their main problem is: THEY ARE PRIVATE!

  143. On the other hand WebAssembly: IS A STANDARD!

  144. On the other hand WebAssembly: IS A STANDARD! AVAILABLE EVERYWHERE!

  145. On the other hand WebAssembly: IS A STANDARD! AVAILABLE EVERYWHERE!

    FOR FREE!
  146. None
  147. So...

  148. So... You can run, you can hide

  149. But you can’t escape WebAssembly :)

  150. Never forget! Compiling for the Web with WebAssembly (Google I/O

    '17)
  151. None
  152. Are we back to the applets?

  153. Are we back to the applets?

  154. Play: https://wasdk.github.io/WasmFiddle

  155. Thank you J