Zaplib post-mortem
zaplib.com
zaplib.com
You could have a great lifestyle and a great business after a few years of work and growing a team of skilled JS performance experts.
Eventually you would probably stumble your way into a solid product once you had solved enough customer problems to see the commonalities (or through your internal tooling etc).
Having a low-engineering concierge service first and then incrementally building solutions is a great way to find real problems.
Pitch them to the various JS conferences and go give the talks. Release them as YouTube videos, and blog posts. Mention the fact that you are available to help teams optimise their front end code, and love doing it.
I think this process would take 3-6 months and you would have a great brand from which to build your business.
It was like every improvement was only marginal, and all of the wasm costs kind of nullified the improvements (especially when combined with the cognitive overhead of a more complex implementation). I never deployed any solutions because it wasn’t compelling enough to introduce the massive change and complexity. Overall I think I spent around 4 months revisiting, tinkering, reading, trying to find a way to squeeze out enough performance to make it worth it.
I’d love to find the right opportunity to use it, but like the author discovered, it’s really difficult. The effort put into making the wasm solution would have been far more valuable learning to manage ui state slightly more efficiently, improving the data structures, finding places to reduce work, etc. in the typescript code.
One thing I wondered: if you work in a monorepo, you might be able to leverage backend code reuse very easily for frontend if you’re using (or able to use) shared data structures across your stack. That was one thing I thought had real potential in terms of developer ergonomics alone. Just keep data in wasm until it’s UI-ready. Don’t type the same data twice, don’t introduce a complex api boundary. Rust is far better at some things than typescript, so I thought that might be worth pursuing even if the performance was only marginally better.
Having said that, I thought a lot of things would be helpful and good with wasm and I was wrong, so that idea could be bad too.
Notably, some Figma views (like when you click the "play" button to view the prototype) render Figma documents using JS, no* Wasm. They are more or less comparably as fast as the C++ renderer, in part because much of the heavy lifting is done by GPU code that isn't C++ or JS anyway.
The main place I think we've seen a performance difference is, as the post observes, high throughput scenarios: for example, decompressing a large file, or parsing through a large binary serialization of a file. But particularly in a browser setting you end up wanting to get your data into a browser API at some point and that often ends up meaning copying data around that eats your performance.
The other main difference that's worth pointing out is memory efficiency. For example, pointers in Wasm are currently 32 bits, which means (at least in principle) a massive graph -- such as a Figma document DOM! -- can be represented with 32-bit C++ pointers rather than 64-bit JS pointers. But even that distinction is not so clear in the presence of pointer compression [1] and there are other graph representation options etc.
In all, my conclusion is that performance does not obviously derive from tool choice because there are so many confounding factors including algorithm choice and path dependence. For another example of this, I often think of this comment[2] by the esbuild author (coincidentally, also behind a lot of Figma code) where he found better performance with Go than Rust, which is not what I think anyone (including him) would expect up front.
[1]: https://v8.dev/blog/pointer-compression [2]: https://news.ycombinator.com/item?id=22336284
* there is some wasm in there actually but it's not for performance reasons
I think it’s becoming clear that as a general replacement of JS WASM isn’t going to achieve what some people are suggesting it could. However it certainly has its place, I’m super excited about being able to use things such as SQLite in the browser and other “lower level” toolkits from reusing existing desktop library’s. That’s where I think it’s going to have enormous success.
As with any FFI system, you pay substantial cost in complexity and to some degree serialization for every function call. But if your app itself - the code in the driver seat - is all inside WASM and you optimize for minimum calls to a framework to touch the DOM by rendering to WebGL, maybe it can be much faster.
WebGL still requires a lot of API calls per frame; WebGL 2 is better because of UBOs and VAOs, but not substantially.
The rust/wasm story is also really bad right now; the latest wasm-pack release has been broken for 6 months now (corrupt release tarball) with nobody interested in fixing it, and wasm-bindgen is practically on life support. Debugging is such a sad experience, too. I regret trying to use rust/wasm, personally.
It's a bit like x86: Other concepts like ARM, RISC and Itanium seem like they should be a lot faster than the outdated, massively retrofitted house of cards that is x86, but with billions of dollars invested into getting it fast, it's really hard to beat it with a different design at a lower budget.
I mean, if you're going to work on something full-time, you probably have a spreadsheet somewhere with an indication of how many paying users are needed before you break-even.
A startup post-mortem that doesn't say what they thought the break-even point was isn't a startup post-mortem, it's a tech-stack post-mortem.
I get the impression from the blog posts that the founders didn't really consider income as a necessity; the reference to their previous initiatives and their future initiatives make it seem like they just want to play with tech.
There need not be break-even analysis, cash flow analysis and such, because if the core product doesn't deliver, the startup goes belly up. The only exception to this rule is if you're in the nutritional supplement business.
Maybe we can say that you should work on problems the market has, and it's especially good if they are problems you have too
I got to sit in for a day during prototyping for user 2 and was impressed but intimidated: reinventing the web stack is a lot of work! The team won me over though. If you have the chance to pair program with JP I highly recommend it, and I expect to be impressed by this team again in the future.
[1]https://github.com/compose-run/client [2]https://composerun.notion.site/Jan-2022-17761ede06f94e2abc42...
FWIW, the most recent Miami Tech Week probably wasn't the best place to talk to engineers working on legit problems in crypto and get excited about it, mostly due to timing.
It overlapped with a few very large crypto conferences in Europe, so everyone was busy flying over there if they were traveling at all!
I didn't take the idea forward because it would've been a heck of a lot of (unpaid) work requiring some fundamental rethinking of the library's architecture, together with learning Rust/AssemblyScript alongside Wasm best practices, etc.
But the main thing that held me back were the bad memories I had of all the work I did when I learned about web workers and attempted something similar a few years ago. That work added a lot of complexity to maintaining/using the library, but in the end failed to deliver the speed increases I was hoping for. The best work I did in 2020 was removing the web workers and their associated complexity from the code base and instead concentrating my efforts on finding speed gains in Javascript.
I love the idea of Wasm, and have had some success in getting code that exports to Wasm - for instance, MediaPipe's Selfie Segmentation ML model - to play nicely with the library[1]. But if I ever want a really fast, Wasm-enabled 2D canvas library I think the best approach would be to build the entire thing in Rust and just have a lightweight JS API to handle the DOM and user interactions.
[1] https://codepen.io/kaliedarik/pen/PopBxBM (warning: the CodePen page will ask for permission to use your device's camera)
I'm doing it for my board game IDE for all the canvas logic because the zero-cost abstractions are helpful for minimizing variance and latency ( http://ide.adama-platform.com/solo/ click single component then drag the box around )
What we need is a TypeScript to native transpiler. I'm sure it will come one day. Rust is great, has a great community and package manager, but I feel it will always be too difficult to use. Rust just doesn't feel like it has sticking power to me. Not as much as TypeScript has at least.