Okay, thank you all. We are going to start now with David, who is going to talk to us about
wasom gc, easy subject, right? Yeah, it's super easy. Can everyone hear me? Okay, cool.
Hi everybody, my name is Dave, I am the CTO at the Sprite Lee Institute, and I'm here to talk
to you about WebAssembly, and specifically the garbage collection proposal that was recently
put into the standard. So we'll quick about Sprite Lee. We're a small US-based 501C3 non-profit,
and our mission is to develop the next generation of decentralized technology for the social
web. And in TSO, we have a number of projects. Just a quick overview. Our big ones are
goblins of the distributed programming environment. We'll cap in the object capability network.
It's a protocol we're developing, not only with ourselves, but with other like-minded organizations.
But the one that's most relevant to this discussion, this talk, is a suit. It's a scheme to
WebAssembly compiler and a WebAssembly tool chain. So here's our little cute pixel art mascot, made by
our executive director, Christine Lamar Weber. And yeah, so real quick, before I get into general
Razum's stuff, so who's a compiler? It's a compiler WebAssembly. The source language is Giles scheme.
We're big fans of Lisp at Sprite Lee. It's a whole program compiler that aims to try to make
this as small of a binary as possible for efficient delivery to clients, you know, particularly
in web browsers. And we target the GC proposal, and we're pretty early adopters of that proposal
before it made it, you know, to phase four, which is like the final phase in the- in the
Wazum community group for adoption to the standard. And notably, it does not use the unscripted
info chain, which most WebAssembly projects use, because it's its own tool chain. We have an
assembler, we have a disassembler, we have a linker, we have a validator, which we then use to
interpret the WebAssembly. So we actually have our own, like, in-house interpreter, which is
really useful for testing purposes. You know, for internal testing, we both have our own interpreter,
and then we also use Node.js as kind of like an oracle of correctness for things. But having
our own interpreter and tool chain gives us a lot of freedom to do as we please with WebAssembly.
And so, like, my experience has been both a user of WebAssembly, but also an implementer of it.
An occasional joiner of hybrid meetings of the WebAssembly community group, but I don't- I don't get it
in there as much as I'd like to. So real quick, who knows what WebAssembly is? Okay, who's actively
like used a project, like worked with WebAssembly directly? Okay, much smaller numbers. So I'll
just do a really quick overview of WebAssembly and move on. So WebAssembly is a portable stack-based
virtual machine. I guess another show of hands, who's ever heard of ASM.js? Okay, a lot of people,
but smaller than the people that heard of WebAssembly. So WebAssembly is like the successor to ASM.js.
That was a project started up in Missouri to basically use a subset of JavaScript that can be
compiled efficiently. And then out of that, became, like, well, why don't we actually have a good
compilation target? That's not JavaScript, and thus WebAssembly was born. So despite WebAssembly,
it's kind of not Web and not assembly. It's like an intermediate representation for a virtual
machine. It's not native, you know, native assembly language. And also, there's run times for the
browser, but there's many, many other run times, both JavaScript-based ones like in Node.js, like
that's using V8, but also many other native run times, such as WasmTime is a big one. And it's
WebAssembly is getting adoption in many non-web contexts, including things like IoT.
So it's developed to the WasmTime community group with W3C, and it's a very approachable
specification. I highly encourage people if you're interested in this at all, take a look at the
WebAssembly spec. You do not have to be an expert to get started into, like, actually work with
this with this technology. It's one of the most approachable web standards I've ever encountered.
You can do a lot with a little effort. So real quick. So we just, the previous side was what is
Wasm. And now, what is WasmTime? This is the WebAssembly text format, WAT, and it looks like a weird
list. It has all the parentheses. It's got the prefix notation. And what you see here is a,
this is an entire WebAssembly module. It's very simple. It has a single exported function named
factorial. And what the code you see in there is just an iterative factorial algorithm. And
things you might, if you're familiar with looking at assembly languages, there's some things that
stand out. There's structured control flow. There's things like loops. You see if blocks,
there's a lot of nesting. So it's not your average assembly language, but it's quite neat.
And if you like this, but you'll very much enjoy working with it, I think. So WebAssembly has a lot of
interesting security properties. Most notably, that it's a capability security system.
And I just realized that throughout my timer, well, let's start it now.
So WebAssembly modules are essentially little secure sandboxes. They have no ambient authority.
They have no means to reach out into the world and say they can HTTP request or read a file or anything
like that. The only, all it can do in terms of talking to the outside world, the things that are
passed into it from the host or who's instantiating the module. So capabilities must be granted
by the host in the form of import. So WebAssembly modules can leave little holes of import, say, a function.
And the module will specify what the signature of that function must be and it's imported name.
And it's up to the instantiator to pass that in. So we'll look at that a little bit more in a bit.
But it allows practical implementation or practical use of the principle of these authority. You can
make a module and you can give it just enough authority to do it. It needs to do it and no more.
If it doesn't need to make an HTTP request, you don't have to give it that ability.
Which means you can tend to run code you don't even trust in a secure way, at least in theory.
And then finally, you know, those are, I've been talking about imports. That's kind of compile time
or instantiation time capabilities. Through WebAssembly, we also get sharing of reference references,
heat-allocated references. And so those themselves are a form of object capabilities. So
very interesting security properties. Just a quick, like, bit of history.
It wasn't one point out that the initial specification, I like to say it's for crabs.
It's for the the rust, the C++, these like static, ahead of time compiled languages.
And particularly languages that use linear memory, they're dealing with like pointers into, you know,
offset into memory. Which meant the wasn't one point. It was really good for like offloading some
number crunching from JavaScript to another language so it could be more efficient. And then kind of doing
your high level stuff in JavaScript. And this is, you know, like, rust uses the LLVM
in tripped into a chain for this a lot of things. That's was a 1.0. You know, some managed memory
languages, languages like, want to have a garbage collector. They used was a 1.0. I think Haskell
is one that did it. There are others. But it has a lot of downsides to doing that. So the big one
being that the binaries are just massive. You're just shipping a lot of code to the user. It's not
bandwidth efficient at all. And the reason being mostly is that you have to ship a garbage collector
in your binary. It's not another great situation. And it's not only the bandwidth cost. It's also
that WebAssembly is not, it doesn't have the ability to do all the things that a native assembly language
can do. Like you don't have threads, for example. And on the web you don't have true threads anyway.
There's other, you know, workers and things like that. So what you ship is not a very good garbage
collector. You ship a really bad garbage collector that way slow space. And then it has its own
separate heap. So if you want to interoperate with with heap values from JavaScript, you're going
to have a bad time. So that's kind of the motivating factor for what was published in WebAssembly
through point out, which is why I was in for the rest of us. It's for those of us that want to use
a dynamic programming languages. So I use scheme, but there's many others that I'll mention a few
later. So last and 3.0 added a hierarchy. This type hierarchy graph you see here of GC managed
reference types. The most important one being the one all the way to the left that kind of has
that diamond shape. It adds things like composite types like heap allocated structs and arrays.
It also has this interesting i31 type, which is a 31-bit integer, which anyone that does language
implementation knows you can use to implement immediate values, things that you don't actually
have to allocate on the heap. They fit in a word, so you can just put them in there efficiently.
So all those things are there. It's really great. And then the other one I want to call your
attention to is all the way on the other side. My left, your right, I guess, is the external type.
That's the way you could say get a JavaScript value, say a dom node or something, and hold on to
that reference in your WebAssembly program and then say pass it back to do some manipulation of a user
interface, for example. So wasn't 3.0, all this stuff with all these new types. The type system
is called iso recursive. Type groups can have recursive references to other types in the group.
They form, you know, so a collection of types form a group, and the canonicalize, which means
different WebAssembly modules that have type groups that are the same shape. At one time are considered
equivalent types. So you can have modules that interoperate by having the same exact type group
definitions. And so a reference of one, understood in one module can be passed over and then
understood and destructured by another module. So it's a way to have interoperability amongst modules.
So with this dynamic language implementation becomes feasible. But why isn't you see is pretty
misunderstood? I tend to read, why isn't this course online and not comment so much because I just
find it pretty frustrating. It feels like it's doomed to repeat the same old things about
GCA. I just feel like there's a lot of misinformation out there about it. So I'd like to bust a few
myths real quick. The biggest one being that Ryzen Gc is below. Why would you put things relevant
to garbage collection in something that's supposed to be in assembly language? That doesn't make any
sense. That's the argument anyway. But as I said before, not having this means we have binaries
that are just massive and inferior to what you could get when your web browser has a world-class
garbage collector sitting right there. And so not only is it not bloated, it makes things
it actually unblope things. The reference types and the garbage collection instructions combined
really only add about 30 or so instructions to the instruction set. And that's nothing compared to
say what the Cindy instructions added and stuff like that. It's a very small set of instructions.
We get smaller binaries and we get faster ones because we actually get to use the good garbage
collectors that are in Chrome and Firefox and it's firing everything. And so just as a personal anecdote
my I work, I say we're a nonprofit, which means we work with not a lot of money. And my small team
was able to port a language to Asmgc on our small budget. And not only that we were able to implement
Asmgc in our own interpreter. So this is not something that needs a team of 10 engineers over
three years to do. You can do this with few resources. So consider that myth busted. I'm just going
to say it. Another big one is that WebAssembly has no DOM access. And that's technically correct,
the best kind of correct. And that's because WebAssembly has no IO access at all. As I said before,
a module has no means to reach the outside world unless the host at instantiation time passes
in some imported functions to do so. And so all IO access is granted and mediated by the host
on the web that's JavaScript. So you can access the web, the DOM API, you just have to import it.
And so just as proof, I won't show you the code right now. But this presentation is a WebAssembly
program that's reaching out to construct these DOM nodes that you see that render these slides.
So it's very much possible. I do this stuff all the time. You can do it today. And I think maybe
what some of the detractors are really getting at is that there's no you do have to call into
JavaScript from WebAssembly. And that's a cheap but not free cost. And so if there's any truth
to this at all, it's that a fast path might be nice. But what is a webAssembly specific interface
to the DOM look like? I certainly don't know. I think that's a hard not to crack. But maybe it
will be at some point. There's other, they're called JS built-ins proposals that have been coming
out. I could foresee some kind of optimization in the future for that. So anyway, I consider this
mostly a myth with a negative trip. And then the final one is, you know, why don't you see it
just for JavaScript haters? It's for people who just don't want to use JavaScript and they're being
really stubborn. And they think that they could just use this. And completely replace JavaScript. And
I'm not a hater, I swear. But I do like to use a non JavaScript by-ing fidget. And it's pretty nice
that I can do so on the client-side web now. JavaScript does have good parts. And my Snarky's
list comment is that the parts that it inherits from scheme mostly. And, you know, ES6 and beyond,
the JavaScript is a pretty good language. Now, it's really not so bad. So it's not a matter of
being a hater or anything like that. But even besides my own personal preferences, there's a clear
desire to use non JavaScript languages on the web anyway. Just as a few example, people want
gradual typing, static typing, and when you use textcript, maybe folks want to use closure
because they use the JVM and they also want to have ship some of that code over to the client.
You got closure script, which compiles JavaScript. You have JSX, which is you're still doing JavaScript,
but then you're also embedding your HTML and stuff in it. And then there's a tool chain to
build all that out. There is a compilation pass. So no matter, most people have some kind of
tool chain involved generating their JavaScript. Even when you get to minification or whatever,
it's like using JavaScript, you're working with some kind of thing that looks like a compiler.
And so JavaScript is not intended to be a compilation target to begin with. And in doing so,
when you compile to JavaScript, you're making a lot of compromises usually, especially if your
source language is not JavaScript plus some extra stuff. TypeScript is JavaScript, but with
the type system. If you want to compile a completely different language, JavaScript, you always
have some compromises. And with WebAssembly, you have fewer. So why isn't you see as JavaScript
replacement? It's more feasible than the common sections we'll need to leave. I think our
project is proof that it can work. I like to say the dream of the 90s is alive because before
JavaScript, JavaScript was the original vision to ship a net escape was a scheme that then became
JavaScript. So it's been 30 years, but looks, schemes and the browser now finally. That's pretty cool.
A hundred percent illumination of JavaScript is not possible because you do need to have some
JavaScript as what boots your WebAssembly modules, what instantiates it. You need a little bit of
JavaScript code, a bit minimum, to handle, to handle, you know, booting that part of the app.
But it's also not really the point. It's not to completely get away from it. It's just to have,
you know, to bring your preferred language into a chain there. So some other languages,
why isn't you see a lot of JVM languages do it? Java, Kotlin, Scala, and then also some,
if you're like a functional programming nerd, like I am, get a little camel there too. It's pretty
great. And there are others, that's just a few. So let's see. There's next section. I just want to
make some high-level comparisons to Blazon versus other things. So, you know, when you compile the
JavaScript, there's some advantages of WebAssembly, and that it's easier to faithfully implement language features.
You actually have a good set of, you know, basic numeric types, just as a simple example,
you know, you actually have instant floats in WebAssembly rather than just having the number type
in JavaScript, which is essentially, you know, a double. You know, if you have a language that's
based a lot around recursive calls, which scheme is in some other functional programming languages,
you have tail calls in WebAssembly, which you don't have in JavaScript. Some JavaScript languages
have a tail call optimization thing built into them, but it's not a specified semantic of JavaScript.
So you can't rely on it as a compiler builder. But you have it in Wazom. So it's easier to bring
another language to Wazom than it is than a JavaScript. They have some similarities.
Both have structured control flow, which means you don't have a go-to that you can use,
which means, in either case, you're probably going to want to use something like the beyond
re-luper algorithm. If you're into your immediate representation that you're compiling to
JavaScript or WebAssembly, uses unstructured control flow, you need to do a pass to convert it to
structured control flow so that you can emit your JavaScript or WebAssembly. So they're similar.
In that regard, as much as I wish this weren't true, it's unlikely to be compiling JS on
file size. I don't have solid numbers to give you on this, but the WebAssembly binary is
tend to be bigger than you want, at least right now. It's much a lower level thing. So it's a
compact binary format, but you need to do a lot of instructions to do things because it's lower level.
So you just tend to still have your shipping more bytes over to your client, and that may
be acceptable, or it might be too much depending on the devices you're targeting.
And then there's WebAPI overhead. Crossing the Wwise and JS boundary is free, as I mentioned earlier,
and you basically need something that resembles a foreign function interface to do it,
and WebAssembly functions are statically types, and there's no like you don't have variable length
argument lists. So a lot of JavaScript methods do operate on those. So you have to kind of
figure out how you want to make your interface to various like JavaScript methods that way.
So there's some translation you have to do. And finally debugging,
WebAssembly really isn't great right now. Sorry to say. The developer tools are just
immature compared to JavaScript. You know, JavaScript had a big headstart, and some of the
JavaScript tools don't apply to WebAssembly. I find that like I like to use Firefox for
a moment, but I often just, I try to look at the disassembly of a binary and Firefox,
it usually just says loading. Nothing ever happens. I don't know. Chrome supports like dwarf,
like a debugging format, but as far as I know other browsers don't, I haven't actually
gotten around to having our tool chain admit dwarf, but whatever. But there's been some
progress on like getting external debuggers linked into editors to kind of work around this,
but I would like to see the dev tools and the browser get better. So JavaScript is a clear win
there. So what if you don't use any language that compiles JavaScript, but if you just
use plain old JavaScript, as I said, JavaScript is quite good these days, so I don't really
see a reason to necessarily want to use WebAssembly for happy with JavaScript. It's hard to beat,
you know, just guessing billion dollars of investment or whatever in the JavaScript ecosystem,
excellent compilers and stuff like that, like WebAssembly's just turned 10 years old.
It's got some catching up to do for those things. And, you know, JavaScript is a relatively
small language, but schemes even smaller. And even with a language of small scheme,
I still need to ship that runtime into the browser. And there's things like schemes,
numeric tower, like rich set of numeric types. It's port IO interface and things like that.
I've got a ship. And that's not free that cost bandwidth, you know, use JavaScript. All that stuff's
already there on the client. The cost can be reduced by exporting, you're like your binary interface
from one module and then importing it from all your other ones. So you can kind of pay the cost once,
and then have everything share that. So that can reduce, but they can't eliminate,
having to ship that runtime over. So, why doesn't the chance to issue NPM, get rid of NPM?
I like JavaScript. I really don't like NPM. I'm not a JavaScript creator, but I am an NPM
hater. Too many high profile security issues for my liking. I've never been happy with the
massive dependency graphs of these like little micro dependencies. And I really don't like
that it's hard, like nearly impossible to say package a self-hostible open source web app
in a Linux distro, because the NPM dependency trees too big to hittle. So I like having a tool
chain that doesn't even use it. Let's see. So, Web Assembly, it's got some room to grow. I think
it's really nice. It's 10 years old, but it's still early days compared to JavaScript. There's just
better tooling around JavaScript, the Web Assembly tooling is still trying to catch up.
It's found. It's places that it's used. Big companies like Figma use it, and they do all sorts
of interesting things. You have people compiling post-grace SQL to Web Assembly or SQL that
this is really cool stuff, but it's niche has not been JavaScript for replacement,
traditionally. Even though we have spread the use it that way, it's not the dominant use case for
Web Assembly. So, I'd say it's not like a slam dunk yet. You've got your favorite language,
you know, just compile it to Web Assembly and you're good to go. I will whatever be that, I'm not sure.
I would like it to be, but all things considered, I'm more or less happy with Web Assembly,
although I want to see some things improve. If you want to read more about this particular
thing, like what are people using Web Assembly for my colleague and lead engineer on Hoot,
Andy Wingo from Agalia. He wrote this article for ACMQ recently, Web Assembly, yes, but for what?
Take a look, really good stuff now. I'm going to end with just looking at some what I think are
promising proposals that are coming in the future of Web Assembly. So, I'm going to cover three
really quick, stackswitching, multi-biter A access, and reference text strings. Stackswitching,
there's no way to capture stack frames, and Wasm right now as specified, which means you can't
really implement, as like a language implementer, you can't implement your own non-local control flow,
if your language has co-retains, generators, unlimited continuations, can't use them. Easily.
We do this in who our Gile uses delimited continuations for a lot of things. If you don't have them,
you really don't have Gile, so we needed them. And so our workaround was to use an explicit stack,
where we actually have Web Assembly tables and stuff that are holding our stack frames, and so that
way we can capture continuations from them. One, it requires a really tricky compiler pass that
took compiler genius Andy Wingo to write that I have a trouble working with when there's bugs in it.
And it adds significant runtime overhead, because we're not using the Web, the Wasm stack,
you're like reading and writing into Wasm tables and things like that. So, things could probably
be like many times faster than they are now, if once we get stackswitching. So, stackswitching adds
a continuation, heat type, and some instructions work with continuations. Multi-biter A access.
If you're using Wasm linear memory, it's usually just like a single instruction to like get
a float, a 32-bit float out of a chunk of memory. Not so if you use heat-balocated arrays. So,
we like to use I8 arrays, like a bite arrays in Wasm Gc. But this code up top is how you get a 32-bit
float out of it. You read four bytes, and you bitch if them in order them together, and then reinterpret
them as a float. It's very inefficient, but there's a proposal to change it to just this
F32.load instruction, which is the same instruction for using linear memory, except you specify
that you want to load it from a heap array. So, that's going to make number crunching with
heat-balocated arrays much faster. Finally, reference type strings. This one's a bit sad.
There's really strings on WebAssembly or not as easy as they ought to be. You kind of have two
main choices. You can work with UTF8 internally in your WebAssembly module, and then copy
them to JavaScript strings at the boundary when you need to. That's what we do presently in
hoot. It's not great, because every time you make an FFI call to JavaScript, you're in a string,
you copy it, and so you're going to run your garbage collector more than you would like to.
Your other option is to use something like the JS string built-ins proposals,
proposal, sorry, which fundamentally works in 16-bit code units, and so you kind of have to
accept the mistakes of the 90s and UTF16, and rather not do it. There's a proposal called string
graph. It adds a string, reference type, and it has instructions to view strings as either
WTF8 or WTF16, which are basically UTF8 and UTF16 with some other details to handle some
of the crazy Unicode stuff, and it's not JS specific. You have one string type, and you can run it
on any Wasm runtime, whether it's in the browser, like a JavaScript host or something else.
Unfortunately, it's stuck at phase one. The Wasm CG community as a whole does not.
Like it, but in hoot, we love it to the point where even though string graph has not been adopted,
our compiler emits string graph, because it's such a useful set of instructions to use as like
an intermediate representation that we emit Wasm in that way, and then we take a pass over it
to strip out all the string graph and replace it with a bunch of stuff using byte arrays,
and then copying when we have to go to JavaScript. My final wish is I haven't seen a proposal yet
for this, but I want to do WebGPU on Wasm with heap allocated arrays. We need a way to view a Wasm
array as a JavaScript type array. We don't have that yet, someone make the proposal, please, if you're
viewing this or here. Yeah, anyway, in conclusion, do you want to meet Wasm in tool chain,
or do you want to be scheme on the browser, try hoot? I think it's pretty great, and I'm very
embarrassed about that. So thank you. Again, I'm a non-profit, I work on non-profit. We need money.
Do you like our work? Please donate. Thank you.
We have to type on default one question. Just one question?
Okay, yeah. Well, Kristina can't be you. I'll be out in the hallway if you want to ask further questions.
Kristina's the only asker, didn't she? Wow. No one else can. This is a completely
non-astery terms question. So the, I guess, so hoot has this wonderful web assembly tool kit,
it's not just for compiling schemes. Correct. G, if, if I have all these features,
is there any reason if I wanted to develop a programming language that compiled to web assembly
today, or operated on web assembly in any other way, that I would choose to use hoot as opposed
to any of the other tool kit set exist, is there any advantage of doing so? Yeah, well, I think
if you're a dynamic programming language minded, you will like that tool chain over the LLVM
and script into a chain. If you like living programs rather than static ones, I think that's a
good base, but also our tool chain has some interesting things. Like having the interpreter means
that we can do things like, you know, have something built in. So with scheme, you have like a,
you often develop from the repule. You have this redevelopment loop, giving you feedback.
Well, you can run a Wazon binary from your repule, and then if there's an error, like a web
assembly error, well, I can drop you into a web assembly debugger in your repule where you can then
inspect function locals step through it, vowel like single web assembly instructions as you attempt
to debug. So I think if you're, if you're at all list curious or dynamic language interested,
it's a good, it's a good place to start. I think the OCaml folks also have their own tool chain,
but I'm the one on stage. So you should use hoots. It's really good. Yeah. Thank you.
Thanks.