{"id":1961,"date":"2019-02-28T12:16:02","date_gmt":"2019-02-28T12:16:02","guid":{"rendered":"http:\/\/dlang.org\/blog\/?p=1961"},"modified":"2021-10-08T11:03:42","modified_gmt":"2021-10-08T11:03:42","slug":"project-highlight-spasm","status":"publish","type":"post","link":"https:\/\/dlang.org\/blog\/2019\/02\/28\/project-highlight-spasm\/","title":{"rendered":"Project Highlight: Spasm"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"alignleft size-full wp-image-1954\" src=\"http:\/\/dlang.org\/blog\/wp-content\/uploads\/2019\/02\/hackathon.png\" alt=\"\" width=\"227\" height=\"148\" \/>In 2014, Sebastiaan Koppe was working on a React project. The app\u2019s target market included three-year-old mobile phones. He encountered some performance issues that, after investigating, he discovered weren\u2019t attributable solely to the mobile platform.<\/p>\n<blockquote><p>It all became clear to me once I saw the flame graph. There were so many function calls! We managed to fix the performance issues by being a little smarter about updates and redraws, but the sight of that flame graph never quite left me. It made me wonder if things couldn\u2019t be done more efficiently.<\/p><\/blockquote>\n<p>As time went on, Sebastiaan gained the insight that a UI is like a state machine.<\/p>\n<blockquote><p>Interacting with the UI moves you from one state to the next, but the total set of states and the rules governing the UI are all static. In fact, we require them to be static. Each time a user clicks a button, we want it to respond the same way. We want the same input validations to run each time a user submits a form.<\/p>\n<p>So, if everything is static and defined up-front, why do all the javascript UI frameworks work so hard during runtime to figure out exactly what you want rendered? Would it not be more efficient to figure that out before you send the code to the browsers?<\/p><\/blockquote>\n<p>This led him to the idea of analyzing UI definitions to create an optimal UI renderer, but he was unable to act on it at the time. Then in 2018, native-language DOM frameworks targeting WebAsm, like <a href=\"https:\/\/mbasso.github.io\/asm-dom\/\">asm-dom for C++<\/a> and <a href=\"https:\/\/chinedufn.github.io\/percy\/\">Percy for Rust<\/a>, came to his attention. Around the same time, the announcement of <a href=\"https:\/\/github.com\/CyberShadow\/dscripten-tools\">Vladimir Panteleev\u2019s dscripten-tools<\/a> introduced him to <a href=\"https:\/\/github.com\/Ace17\/dscripten\">Sebastien Alaiwan\u2019s older dscripten project<\/a>. The former is an alternative build toolchain for the latter, which is an example of compiling D to <a href=\"https:\/\/github.com\/emscripten-core\/emscripten\">asm.js via Emscripten<\/a>. Here he saw an opportunity to revisit his old idea using D.<\/p>\n<blockquote><p>D\u2019s static introspection gave me the tools to create render code at compile time, bypassing the need for a virtual DOM. The biggest challenge was to map existing UI declarations and patterns to plain D code in such a way that static introspection can be used to extract all of the information necessary for generating the rendering code.<\/p><\/blockquote>\n<p>One thing he really wanted to avoid was the need to embed <a href=\"https:\/\/reactjs.org\/docs\/introducing-jsx.html\">React\u2019s Javascript extension, JSX,<\/a> in the D code, as that would require the creation of a compile-time parser. Instead, he decided to leverage the D compiler.<\/p>\n<blockquote><p>For the UI declarations, I ended up at a design where every HTML node is represented by a D struct and all the node\u2019s attributes and properties are members of that struct. Combined with annotations, it gives enough information to generate optimal render code. With that, I implemented <a href=\"https:\/\/github.com\/skoppe\/d-wasm-todomvc-poc\">the famous todo-mvc application<\/a>. The end result was quite satisfying. The actual source code was on par or shorter than most javascript implementations, the compiled code was only 60kB after gzip, and rendering various stages in the todo app took less than 2ms.<\/p><\/blockquote>\n<p>He announced his work on the D forums in September of 2018 (<a href=\"https:\/\/skoppe.github.io\/d-wasm-todomvc-poc\/\">the live demo is still active<\/a> as I write).<\/p>\n<p>Unfortunately, he wasn\u2019t satisfied with the amount of effort involved to get the end result. It required using <a href=\"https:\/\/wiki.dlang.org\/LDC\">the LLVM-based D compiler, LDC,<\/a> to compile D to LLVM IR, then using Emscripten to produce asm.js, and <a href=\"https:\/\/github.com\/WebAssembly\/binaryen\">finally using binaryen<\/a> to compile that into WebAssembly. On top of that\u2026<\/p>\n<blockquote><p>\u2026you needed a patched version of LLVM to generate the asm.js, which required a patched LDC. Compiling all those dependencies takes a long time. Not anything I expect end users to willfully subject themselves to. They just want a compiler that\u2019s easy to install and that just works.<\/p><\/blockquote>\n<p>As it happened, <a href=\"https:\/\/github.com\/ldc-developers\/ldc\/releases\/tag\/v1.11.0\">the 1.11.0 release of LDC<\/a> in August 2018 actually had rudimentary <a href=\"https:\/\/wiki.dlang.org\/Generating_WebAssembly_with_LDC\">support for WebAssembly baked in<\/a>. Sebastiaan started rewriting the todo app and his Javascript glue code to use LDC\u2019s new WebAssembly target. In doing so, he lost Emsripten&#8217;s bundled musl libc, so he switched his D code to use <code>-betterC<\/code> mode, <a href=\"https:\/\/dlang.org\/blog\/2017\/08\/23\/d-as-a-better-c\/\">which eliminates D\u2019s dependency on DRuntime<\/a> and, in turn, the C standard library.<\/p>\n<p>With that, he had the easy-to-install-and-use package he wanted and was able to get the todo-mvc binary down to 5kb after gzip. When he announced this news in the D forums, he was led down a new path.<\/p>\n<blockquote><p>Someone asked about WebGL. That got me motivated to think about creating bindings to the APIs of the browser. That same night I did a search and found underrun, <a href=\"https:\/\/js13kgames.com\/entries\/underrun\">an entry in the 2018 js13k competition<\/a>. I decided to port it to D and use it to figure out how to write bindings to WebGL and WebAudio.<\/p><\/blockquote>\n<p>He created the bindings by hand, but later <a href=\"https:\/\/heycam.github.io\/webidl\/\">he discovered WebIDL<\/a>. After <a href=\"https:\/\/skoppe.github.io\/spasm\/examples\/underrun\/\">the underrun port<\/a> was complete, he started work on using WebIDL to generate bindings.<\/p>\n<blockquote><p>It formed very quickly over the course of 2\u20133 months. The hardest part was mapping every feature of WebIDL to D, and at the same time figuring out how to move data, objects and callbacks between D and Javascript. All kinds of hard choices came up. Do I support <code>undefined<\/code>? Or optional types? Or union types? What about the \u201cany\u201d type? The answer is yes, all are supported.<\/p><\/blockquote>\n<p>He\u2019s been happy with the result. D bindings to web APIs are included in Spasm and they follow the Javascript API as much as possible. A post-compile step is used to generate Javascript glue code.<\/p>\n<blockquote><p>It runs fairly quickly and generates only the Javascript glue code you actually need. It does that by collecting imported functions from the generated WebAssembly binary, cross-referencing those to functions to WebIDL definitions and then generating Javascript code for those.<\/p><\/blockquote>\n<p>The result of all this is Spasm, <a href=\"https:\/\/github.com\/skoppe\/spasm\">a library for developing<\/a> single-page WebAssembly applications in D. The latest version is always available <a href=\"https:\/\/code.dlang.org\/packages\/spasm\">in the DUB repository<\/a>.<\/p>\n<blockquote><p>I can\u2019t wait to start working on hot module replacement with Spasm. Many Javascript frameworks provide it out-of-the box and it is really valuable when developing. Server-side rendering is also something that just wants to get written. While Spasm doesn\u2019t need it so much to reduce page load times, it is necessary when you want to unittest HTML output or do SEO.<\/p><\/blockquote>\n<p>At the moment, his efforts are directed toward creating a set of basic material components. He\u2019s had a hard time getting something together that works in plain D, and at one point considered abandoning the effort and working instead on a declarative UI language that compiles to D, but ultimately he persisted and will be announcing the project soon.<\/p>\n<blockquote><p>After the material project there are still plenty of challenges. The biggest thing I have been postponing is memory management. Right now the allocator in Spasm is a simple bump-the-pointer allocator. The memory for the WebAssembly instance in the browser is hardcoded to 16mb and when it&#8217;s full, it&#8217;s full. I could grow the memory of course, but I really need a way to reuse memory. Without help from the compiler &#8211; like Rust has &#8211; that either means manual memory management or a GC.<\/p><\/blockquote>\n<p>One way to solve the problem would be <a href=\"https:\/\/github.com\/dlang\/druntime\">to port DRuntime<\/a> to WebAssembly, something he says he\u2019s considered \u201ca few times\u201d already.<\/p>\n<blockquote><p>At least the parts that I need. But so far the GC has always been an issue. In WebAssembly, memory is linear and starts at 0. When you combine that with an imprecise GC, suddenly everything looks like a pointer and, as a consequence, it won\u2019t free any memory. Recently someone wrote a precise GC implementation. So that is definitely back on the table.<\/p><\/blockquote>\n<p>He\u2019s also excited that he recently ran WebAssembly generated from D on Cloudflare workers.<\/p>\n<blockquote><p>The environment is different from a browser, but its the same in many ways. This is all very exciting and lots of possibilities will emerge for D. In part because you can generate WebAssembly binaries that are pretty lean and mean.<\/p><\/blockquote>\n<p>We\u2019re pretty excited about the work Sebastiaan is doing and can\u2019t wait to see where it goes. Keep an eye on the <a href=\"https:\/\/twitter.com\/dlang_ng\">Dlang Newsfeed (@dlang_ng)<\/a> on Twitter, or <a href=\"https:\/\/twitter.com\/D_Programming\">the official D Twitter feed (@D_Programming)<\/a> to learn about future Spasm announcements.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Spasm allows Single Page Apps to be written in D and compiled into WebAssembly. In this post, Spasm creator and maintainer Sebastiaan Koppe explains how the project came about, what it does, and where it&#8217;s going.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[12,13],"tags":[],"_links":{"self":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1961"}],"collection":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/comments?post=1961"}],"version-history":[{"count":13,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1961\/revisions"}],"predecessor-version":[{"id":2027,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/posts\/1961\/revisions\/2027"}],"wp:attachment":[{"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/media?parent=1961"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/categories?post=1961"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dlang.org\/blog\/wp-json\/wp\/v2\/tags?post=1961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}