Why WebAssembly Can't Win - バイリンガル字幕
Tree Shaking, the horticulturally misguided algorithm.
I you're like, what?
I clicked a video about WebAssembly.
Why am I reading about this?
I promise it'll all make sense as we go forward,
because Tree Shaking, WebAssembly, JavaScript, and the state of the browser, they're all a bit of a mess.
This article from my quick skin seemed really cool and I'm excited to dive in with y'all.
Let's talk about Tree Shaking.
Looking up, through the trough, but first, I need to talk about WebAssembly's dirty secret.
Despite all of the hype, WebAssembly has had limited success on the web.
Limited is putting it lightly.
It's very rare we actually use WASM for anything other than like image and video processing online.
Very few sites are using WASM to control what you see as you explore the site.
There are very few sites where you click a button and then WASM deals with whatever is supposed to happen as a result.
Incredibly rare.
There is Photoshop, which does appear to be a real success.
Five ago there was Figma, though they don't talk much about the Wasm stuff these days.
There are quite a number of little NPM libraries that use Wasm under the hood, usually compiled from C++ or Rust.
I think Blazer probably gets used for a few in-house corporate apps, though I could be fooled by their marketing.
You might recall the hype demos of 3D first-person shooter games with Unreal Engine again from 5 years ago,
but that was the previous major release of Unreal, and was always experimental.
The current Unreal 5 version does not support targeting Wasm.
I didn't actually know that, but I haven't seen any good Unreal demos in the browser in a time, so it does make sense.
Don't get me wrong, I think WebAssembly is great.
in the off-the-web environments, and think it's going to be a key and growing part of the web platform.
I suspect, though, that we're only just now getting past the trough of disillusionment.
This is a classic.
It's my favorite startup chart,
where technology happens,
we get really hyped, we realize the hype's not real, we crash, and then we slowly get to where things actually makes sense.
well at bringing large C++ programs to the web.
I know that it took quite some work,
but I understand the end result to be essentially the same source code just compiled for a different target.
Similarly, for the JavaScript module case, Wasm finds success in getting legacy C++ code
onto the web, also as a way to write new web targeting Rust code.
There are often tasks that JavaScript doesn't do very well at, or which need a shared implementation between client and server deployments.
On other hand, Wasm has not been a web success for DOM-heavy apps.
Nobody is talking about rewriting the frontend of WordPress.com in Wasm, for example.
Depends on which communities you ask, although I will say, it seems like that has stopped.
We were definitely in a bit of a phase where we were pretending they could just rewrite their whole website in Rust in Wasm.
That's not a real thing.
Why is that?
It may sound like a silly question to you, Wasm just isn't that good at that stuff.
But why?
If you dig down a bit, I think it's that the programming models are just too different.
The primary programming model is JS, a language with dynamic typing and manage memory, whereas Wasm 1.0 was about static typing and linear memory.
Getting to the DOM from Wasm was a hassle that was overcome all time.
only by the most ardent of the true Wasm faithful.
Relatedly, Wasm has also not really been a success for languages that aren't like C or Rust.
I am guessing that WordPress.com is written mostly in C++.
One of the sticking points for this class of language is that C-sharp,
for example, will to ship with a garbage collector and that it's annoying to have to do this.
Check my article for March this year.
year for more details.
Quorum and Firefox have already shipped Wazib Garbage Collection,
and Safari shouldn't be far behind thanks to the efforts from my colleague, Asumu Takikawa, hopefully I got your name right.
This is an extraordinarily exciting development that I think will kick off a whole nother gardener hype cycle,
as more languages start to update their tool changes to support Wazim.
If you don't like my peaches, oh boy, this brings us to the meat of today's note.
Web Wasm will win where compilers create compact code.
If your language's compiler tool chain can manage to produce useful Wasm in a file that's less than a handful of over-the-wire kilobytes,
you actually have a chance to win.
If your compiler can't do that,
you'll have to instead rely on hype and captured audiences for adoption, which at best stable equilibrium until you figure out what's next.
Whew, we're getting spicy spicy here.
I like this a lot.
In the JS world, managing bloat in deliverable sizes is a huge industry.
Yeah, we've spent so much time talking about bundlers.
How many of my recent videos are arguably about bundlers?
We just go to my channel, where you can see them live right now, by the way.
We're only videos live.
This one's about bundlers.
We're at one so far.
I expecting this to be slightly worse, honestly.
I talk about bundlers a lot.
Package managers kind of the same deal.
We'll count that.
So we're at two.
This one's about JS bundlers being rewritten from Go to Rust, so that counts for sure.
We're at three.
Winter JS is different run time, so can't quite count it, even though it's competing with BUN, which also a Bundler.
I talk about Bundlers a lot.
Although I will make the point that my most recent Bundler video kind of bombed,
so it seems like the ecosystem might be burnt out of Bundlers, we'll figure out what that means in the future.
Anyways, Bundlers like ESBuild are a ubiquitous part of the tool chain, compiling down a
set of JS modules to a single file that should include only the functions and data types that are used in a program,
and additionally applying domain-specific size squishing strategies, such as minification, which makes monikers more minuscule.
So if you give something a big name, minification makes the name small.
Good stuff, let's focus on tree shaking.
Yes, the thing that this article supposedly actually about, even though the impact on WebAssembly is one of the most important pieces.
So let's focus on tree shaking.
The visual metaphor is that you write a bunch of code and you only need some of it for any given page.
So you imagine a tree whose branches are the modules that you use and whose leaves are the individual definitions in that module,
and then you violently shake the tree, probably killing it.
And also, birds.
The thing that's left still attached is what is actually needed.
I have a feeling after reading this, this guy's not gonna like tree shaking too much, although a analogy.
This isn't how trees work though.
Holding the trunk doesn't give you information as to which branches are somehow necessary for the tree's mission.
It also primes your mind to look for the wrong fixed point,
removing unneeded code instead of keeping not only the necessary code, interesting one, what is this link to?
Fixed and strike mandates.
This from over 10 years ago.
This like a math thing.
I'm smart enough for that.
I have JavaScript dev.
But shaking's an evocative name.
And so despite its horticultural and algorithmic inaccuracies, we'll stick to it.
fair.
It's a fun name, even if it means nothing.
The thing is that the maximal tree-shaking for languages with a thicker runtime has not been a huge priority.
Consider Go.
According to the Golang wiki, the most trivial program compiled to Wasm from Go is two megabytes.
And adding imports can make this go to 10 megs or more, or look at Pyodide, a Python WebAssembly port.
The example downloads about 20 megs of data.
These are fine sizes for tech demos, or in the limit, very rich applications, but they aren't winners web dev.
This is a very important key I think people mix.
If you're building rich applications that are heavily interactive,
things like Photoshop or Figma,
graphical transformations and heavy math done in order to make the experience good,
downloading a few megs of data to make that experience better is reasonable.
If this is the baseline for entry,
writing your website for your blog in Go or Python is incredibly dumb,
and it's a huge gap between the web that we use every day.
and the technologies that people are excited about for the web.
Like gap is just so big in the expectations,
the way browsers work, the size of these bundles, that it's hard to take anyone seriously who thinks the future of the web is rust.
So let's shake a different tree.
To be fair,
both the built-in Wasm support for Go and Pyodide ports a Python,
derived from the upstream tool chains,
where producing small binaries is nice,
But not necessary on a server who cares how big the app is oh boy server component
plug I will say is my favorite things about server components is the fact that I can just have giant code and not worry about
Getting to the user because only the parts the user is actually like rendering and consuming on client are shipped to them
Watch any of my server component videos to hear more about that the one about airplane proof code It's a really good example of this.
And indeed, when targeting smaller devices, we to see alternative implementations of the tool chain.
For example, MicroPython or TinyGo.
TinyGo has a Wasm backend that can apparently go down to less than a kilobyte, even.
Interesting.
Never heard of TinyGo.
Interesting.
It reads his library is used by the Go language tools alongside LLVM.
It never said to go to be an embedded language, and so it got serious problems.
Oh, Rob Pike.
I love Rob's honesty.
I don't love his design decisions, his choices, his language, or much else about him.
But at least he's honest, and that's a pretty great quote to admit that Go in embedded systems is terrible.
Apparently, TinyGo actually keeps the Go memory model, which implies garbage collection of some sort.
Very interesting project.
The original reasoning was, if Python can run on microcontrollers, then certainly Go should be able to run on even lower level micros.
It is kind of funny that Python could go lower level than Go, pretty funny concept.
These alternative toolchains often come with some restrictions or peculiarities.
Let's take a look at the differences with TinyGo.
The regular compiler inflicts all major goal language features,
although some details If you're wondering does TinyGo support feature X, we often cannot give a good answer.
The of this page gives a good indication,
but other than that, you will just have to try for yourself to see whether a particular piece of software works with TinyGo.
So Sego isn't gonna work great, Reflection.
Yeah, there's a custom Reflect package that's been re-implemented and mostly works.
Maps work fine, maybe slower than you expect them to be.
There are a reasons for this,
one of which is that some types, like structs, may internally be compared using Reflection instead of using a dedicated hash compare function.
There's a bunch of standard library stuff that is not supported,
but they have a list of the things that do compile, but compiling does not imply that it works entirely.
Oh boy.
Garbage collection generally works fine,
but may not work as well on very small chips and on web assembly It is also a slower than the usual go-garbage collector good to know so it does work on Wasm
But not as well,
and it's also very slow So we just saw there are definitely some differences here and although we can consider this to be an evil of sorts
It is to be expected that the target platform exhibits some co-design feedback on the language
Their point I do think that we've been spoiled nowadays that like windows Mac and Linux are finally getting to a
Where we can target them without having to write too much custom code for each one
But we're like just getting there like just barely
So the idea that the platform in this case the web and Wasm should have some say over the language Yes,
but also In particular running in the sea of the dom is sufficiently weird that a Wasm targeting python program will necessarily Python program.
To be fair,
UI and Python has been a mess for literally ever,
so Python having a real UI layer in this case of the DOM sounds actually pretty compelling,
but yeah, it is fundamentally different from how we write native Python.
Still, I think as Toolchain authors we aim to provide the same language, albeit possibly with a different implementation of the STS.
I am sure that the closure script developers would prefer to remove their page documenting the differences with closure, if they could.
And perhaps if Wasm was to become a viable target for closure script, they will.
On algorithm, to recap, now that it supports Wasm could be a winner for web development in Python and other languages.
You would need a different tool chain and an effective tree sh- So that user experience does not degrade.
So let's talk about the tree shaking.
Oh boy.
I work on the hoot scheme compiler, which targets Wasm with garbage collection.
Is this guy a scheme guy?
Are kidding?
I was low when you're not signing to GitLab.
There's the why GitLab button, so trying so hard to pull people over.
Who does the code name for the guile web assembly project launched by the sprightly institute?
In to the compiler, who a full web assembly tool chain with a watt parser, an an assembler, an et cetera.
Is guile, like, the new scheme?
Yeah, it's implementation of scheme.
Yeah.
They, they really are putting scheme in the frickin room.
Regardless, if this guy's putting scheme in the browser, he what he's talking about.
This just way overqualified him for every other point he said.
This is going to be fun.
So he's working on the Hoot scheme compiler, which targets Wausen with GC.
We manage to get down to 70 kilobytes or so right now, in the minimal main compilation unit.
And we are aiming for lower.
Auxiliary compilation unit.
facilities, the current exception handlers, and from the main module can be sub-kilobytes.
Being sub-one-kilobyte for a module in Wazimx is actually pretty huge.
Getting has been tricky, though, and I think it would be even trickier for Python.
Some background.
Like Or Wiffle?
What the fuck's a Wiffle?
You scheme people are insane, so whatever wiffle is, some other alternative to scheme, or some other scheme-based thing.
The compiler propends a prelude onto user code, tree shaking happens in a number of places.
There's partial evaluation which will evaluate unused bindings for effect, possibly eluding them.
Or a lighting.
Why is this guy like these words?
Overall, this has been a very readable article, but what the fuck's a lighting?
CBS is like something about call, so they're checking to see how often things are called, following only reference functions, values, and edges, like renumbering.
There's an explicit deadcode elimination pass which tries to a wide, unused, effect-free allocations, a situation that can arise due to other optimizations.
Finally, there's a standard library which is written in rawish wasm,
whose is, like, global tables, imports, functions, et are included in the residual binary only as needed.
Generally speaking, procedure definitions, like and closures, are the easy part.
You just include only the functions that are referenced by the code.
In a language like SCME, this gets you a long way.
However, there are three immediate challenges.
One that the evaluation model for the definitions in the prelude is Let Wreck Star.
The scope is recursive but ordered.
Binding values can call or refer to previously defined values, or capture values defined later.
Evaluating the value of a binding requires referring to a value only defined later, then that's an error.
Again, for procedures is trivially okay, but as soon as you have non-procedure definition
compiler won't be able to prove this nice only refers to earlier bindings property.
In the case that fixing let-rec reloaded algorithm will end up residualizing bindings that are set,
which all of the tree-shaking passes above require the delicate DCE pass.
Okay.
I knew early into this paragraph that this was smart people speak, but by the end, yeah.
Yeah.
If I understand correctly, this is saying that it's hard to know if a is actually being used unless it's within an isolated procedure.
Oh, Chris is here helping too.
Finally, smart compiler people.
CPS goes to the one process child.
Never mind, thought you were going to be helpful, Chris.
My mistake.
I saw your name, I saw the abbreviation and assumed you were going to be helpful.
Well, I got trolled.
I'll take the L.
Worse, some of these non procedure definitions are record types, which have V tables that define how to print a record, how to check if a value is an instance of the
record and so on.
These V table callbacks can end up keeping a lot more code alive, even if they are never used.
Go to this later.
Oh boy.
Similarly, say you print a string via display.
Well, now not only are you bringing in the whole buffered IO facility, but you're also calling a highly polymorphic function display can print anything.
There's a case for bit vectors.
So pull in code for bit vectors.
There's a case for pairs.
So you pull in code for that too.
Yeah, the thought that display can print anything means either after rewrite display to
Or you just deal with it and import everything this display could display anything One solution is to instead call writeString,
which only writes strings and not general data.
You'll still get the generic buffered I.O.
facility, though, even if your program only uses one kind of port.
This brings me to my next point, which is that optimal tree shaking is a flow analysis problem.
Consider display.
If we know that a program will never have bit vectors, then any code in display that works on bit vectors is dead.
And we can follow the branches that guard it.
But to know this, we have to know what kind of arguments display is called with, and for that we need higher level flow analysis.
Problem is exacerbated for Python in a few ways.
One, because object-oriented dispatch is programming.
How do you know what foo bar actually means?
Depending on foo,
which means you have to thread around representations of what foo might be everywhere, and everywhere's caller, and everywhere's caller's caller, and so on.
This is a very important point.
I've covered static,
Hermes, a in the past,
So if you're somehow not familiar with static Hermes, it's a JavaScript compiler that compiles your JS to basically be native assembly code.
This example here is from the presentation.
You watch my whole video about static Hermes.
I'm sure you should search Hermes I'll come up pretty quickly.
The goal here is to show that you kind of need type safety in order for this to work.
Because if you're dealing with all the different types of data and you're doing that at a low enough level, things get messy.
The problem is what Python is dealing with there,
where if your language is unsound and you want to figure out what isn't, isn't being used, is really difficult to do such.
In Hermes,
in Hermes,
the solution is to have really strict compiler rules,
where you have to have type definition,
so that the compiler knows what the data's actually shaped like and what it actually is supposed to do.
So it's weird to think in order to use the static JS compiler to make your JS faster,
you can actually write JavaScript,
you have to write flow or TypeScript because you need the type definitions in order for this to work and behave as expected.
Crazy when you think about it, but it does make sense and it is important that they're handling these problems.
because we need this to work.
We need this to work well.
Which, again, is what makes this so interesting, is that since these languages we want to use don't have these strict definitions, compiling to figure
out what we do and don't need is nearly impossible.
We don't have that data included in our code definitions, it doesn't exist.
So now we have to generate it, and that generation is an incredibly difficult challenge that seems like everyone else is struggling with here, too.
Specifically, the idea of higher-level flow analysis.
Secondly, look-o-in Python is generally more dynamic than in Scheme.
The next point he makes is even more things that are hard because Python's dynamic,
and since Python's dynamic, we have any idea what it needs almost ever.
But finally, and perhaps relatedly, the object of tree-shaking in Python is a mess of modules rather than a big term with lexical bindings.
This like JavaScript, but without the established ecosystem of tree-shaking bundlers, Python has its work cut out for some years to go.
In short, with garbage collection, Waza makes it thinkable for the first time to do DOM programming in languages other than JS.
It will only be feasible for mass use.
The resulting modules are small, and that means significant investment on each language's tool chain.
Often, this will take the form of alternative tool chains that incorporate experimental tree-shaking algorithms and whose alternative standard libraries facilitate the tree shaker.
Well, I'm off to lunch.
Happy-bling, comrades.
This is a phenomenal post.
this was from back in 2023 near the end of the year yeah Wingo log you killed it
this was dope yeah I had suspicions and beliefs about a lot of these things but
I did not think anywhere nearly this strongly about it yeah definitely
recommend checking out his blog if you're curious there's a lot of cool stuff here links in the description That a great article.
I was always skeptical of Wasm in the browser,
but this puts my points better than me and shows even more challenges I hadn't imagined yet.
Curious what you guys think though,
is the future one where we have more Wasm in the browser and we're using other languages or are we stuck with JavaScript
Let me know what you think and don't check the blog out.
Until next time, peace.
さらなる機能をアンロック
Trancy拡張機能をインストールすると、AI字幕、AI単語定義、AI文法分析、AIスピーチなど、さらなる機能をアンロックできます。

主要なビデオプラットフォームに対応
TrancyはYouTube、Netflix、Udemy、Disney+、TED、edX、Kehan、Courseraなどのプラットフォームにバイリンガル字幕を提供するだけでなく、一般のウェブページでのAIワード/フレーズ翻訳、全文翻訳などの機能も提供します。

全プラットフォームのブラウザに対応
TrancyはiOS Safariブラウザ拡張機能を含む、全プラットフォームで使用できます。
複数の視聴モード
シアターモード、リーディングモード、ミックスモードなど、複数の視聴モードをサポートし、バイリンガル体験を提供します。
複数の練習モード
文のリスニング、スピーキングテスト、選択肢補完、書き取りなど、複数の練習方法をサポートします。
AIビデオサマリー
OpenAIを使用してビデオを要約し、キーポイントを把握します。
AI字幕
たった3〜5分でYouTubeのAI字幕を生成し、正確かつ迅速に提供します。
AI単語定義
字幕内の単語をタップするだけで定義を検索し、AIによる定義を利用できます。
AI文法分析
文を文法的に分析し、文の意味を迅速に理解し、難しい文法をマスターします。
その他のウェブ機能
Trancyはビデオのバイリンガル字幕だけでなく、ウェブページの単語翻訳や全文翻訳などの機能も提供します。