Let's start with some basics of Web Development, which involve execution speed, memory usage, garbage collection times, frame rates, and ease of development. Having Web Assembly as a tool can (and does) address many of these concerns which are speed and memory usage.
AssemblyScript as my tool of choice.
There is a lot to be said about AssemblyScript and I wrote a primer about it here. I want to use it as an example of why Web Assembly isn't exactly always the answer to solve every one your problems. You can check out the GitHub here (and give it a star):
npm install away.
The core team members and most contributors do this open source work in their free time. If you use AssemblyScript for a serious task or plan to do so, and you'd like us to invest more time on it, please donate to our OpenCollective. By sponsoring this project, your logo will show up above. Thank you so much for your support!
For our purposes today, we will talk about some of the problems that I faced when developing the
as-pect testing command line tool. More specifically I hit a snag when trying to make
as-pect faster by pushing more logic into Web Assembly.
Everyone knows that Web Assembly is fast and efficient bytecode. Thus, it should be the case that porting your application into Web Assembly should be the optimal solution. This is the very assumption I started with.
node.js runtime via command line. When it came time to start the optimizing process, I noticed that it was possible to move all of the testing logic into the web assembly testing module itself.
A first gut reaction might be to think that because the test logic now runs in Web Assembly, that things would become way faster.
This was not the case.
Why not port the testing framework into AssemblyScript? Well, imagine needing to compile over 25+ entry files that contain some
describe() function calls. Each of them must be interpreted separately for reporting and organizational reasons. Even worse, WebAssembly currently doesn’t support dynamic linking of functions. Thus each test’s binary must be statically linked. What does that mean? A copy of the entire testing library must be put into each testing module.
This might not seem like a big deal, but
as-pect itself runs over 200 tests over the course of 25+
.spec.ts files. This means 25 copies of the testing framework need to be made. This framework would need to be compiled, interpreted, and bootstrapped nearly 25 more times overall.
This was not the only problem. It was compounded by the fact that not every single testing framework function can be described in web assembly. For instance, getting the current time must currently be obtained using the
performance.now() function. The
wasi alternative is not supported in
The overall tradeoff was a miserable 10% speed increase in testing speed, which was only 25ms per file already. This didn't make things any faster. It made the testing framework as a whole way worse. This is because compilation times were the bottleneck, not the testing. Also, this direction causes problems with feature flexibility.
Spending your time thinking that you can port every problem you have to Web Assembly is not productive. You may be creating problems you previously did not have to deal with. I know that AssemblyScript can make your TypeScript faster, but it's not always the solution. Don't let this fact prevent you from trying to make your software better. Instead, let it guide you down a path that utilizes the right tool for the job.
For example, letting
node.js immediately helps you circumvent the aforementioned slow compile times and cumbersome build steps unless you are coding in TypeScript. Qualitative top-level tasks like adding and testing a new command line interface option will happen much quicker. There are many tools already unit tested and optimized just for this kind of purpose, and thus, we should be responsible for standing on the shoulders of giants to achieve our higher goals.
Attack your problems like the wise builder and not as the zealous idea seeker.