close

DEV Community

Cover image for Most Apps Are Slower Than They Need to Be — Here’s Why (Live Demo🛸)
Sylwia Laskowska
Sylwia Laskowska

Posted on

Most Apps Are Slower Than They Need to Be — Here’s Why (Live Demo🛸)

Practical WebGPU and WebAssembly performance

We’re a quarter into the 21st century, and the browser has quietly evolved into something much more than just a UI layer. It can run complex computations, leverage the GPU, process audio, simulate physics, and even run machine learning models. And yet… most of the time, we still treat it like a tool for forms and dashboards.

I wanted to show what happens when we actually take advantage of what the platform already gives us.

The jsday conference in Bologna has just come to an end, and it was honestly amazing. If you’re wondering whether it’s worth attending events like this — it absolutely is. It’s an endless source of inspiration, far beyond what you get from articles or tutorials. If you have a minute, I’d really appreciate a like on my LinkedIn post

Woman speaking at converence Woman standing near conference banner Icecream

If you’ve been following my posts, you probably know that my talk was about WebGPU and WebAssembly, and what we can gain by using them in the browser.

So what are these two technologies, and why does it make more sense to talk about them together rather than separately?

They are complementary by design. WebAssembly runs on the CPU and allows us to execute low-level, compiled code directly in the browser. WebGPU, as the name suggests, gives us access to the GPU — not in some abstracted, limited way, but in a relatively direct and powerful form.

If you want a deeper dive, I’ve written more about them here:
WASM → https://dev.to/sylwia-lask/will-webassembly-kill-javascript-lets-find-out-live-demo-43ln
WebGPU → https://dev.to/sylwia-lask/why-webgpu-feels-like-the-future-of-the-web-live-demo--2bjh

But instead of talking about them in isolation, I wanted to show a concrete example of what happens when you combine them.

Because I’m not a fan of theory without practice, I built a small demo.

👉 Repo: https://github.com/sylwia-lask/text-goes-boom
👉 Live demo: https://sylwia-lask.github.io/text-goes-boom/
(Fair warning — especially the JS canvas benchmark can get your CPU quite warm 😅)

What does it do? You type text into an input field. The text is converted into particles. And when you click and drag your mouse across it… the text explodes.

Completely useless? Yes. Slightly addictive? Also yes 😅

App screenshot


What’s happening under the hood?

First, the text from the input is rendered into an image bitmap using plain JavaScript and Canvas 2D. This is exactly the kind of task where the classic browser APIs are already perfectly sufficient, and there’s no real reason to move it elsewhere — especially for a demo like this.

Next, the bitmap is passed to WebAssembly. This is where I run a deliberately “somewhat over-engineered” algorithm that maps the image into particles. I wanted WASM to actually have something meaningful to do, and let’s be honest — it also just looks cooler this way. Out of curiosity, I benchmarked it against an equivalent implementation written in JavaScript.

WASM vs JS benchmark. WASM is 2.5x fater

As you can see, this is where we get the first tangible gain. WebAssembly is roughly 2–3× faster in this case. And this isn’t even a best-case scenario — I put quite a bit of effort into optimizing the JavaScript version as well, just to make things fair and not give Rust an easy win.

In this particular demo, the difference doesn’t matter that much because this step only runs once during rebuild. But it’s not about this one case — it’s about the order of magnitude. What happens if you need to perform a similar operation hundreds or thousands of times? That’s where this starts to become very real.

And then comes the part where things get interesting.

The particles are passed to WebGPU — and this is where the browser really starts to flex.

The “classic” JavaScript + Canvas 2D implementation starts struggling on my machine at around 40k particles.

App canvas 2d implementation

Frame rate drops, everything slows down, and you can feel the limits pretty quickly.

Meanwhile, WebGPU… doesn’t even flinch.

More than 500,000 particles. Each with its own physics. Smooth animation. Stable FPS.

WebGPU renders more than 500k particles

At this point it stops being a small optimization and starts feeling like a completely different class of capability. The same browser, the same app, the same machine — but a totally different level of performance, simply by using the right tool for the job.


Where does this actually matter?

This is obviously not your typical frontend CRUD setup. You probably don’t need WebGPU to build a dashboard or a form, and in many cases the real bottleneck is the network, not computation.

But there are entire classes of problems where this approach makes a huge difference: real-time data visualization, physics simulations, graphics-heavy interfaces, audio processing, games, image or video transformations, and of course — matrix-heavy workloads like machine learning and LLMs running directly in the browser.

And the funny thing is, you don’t need this… until suddenly you really do. A product evolves, requirements grow, performance becomes an issue, or you want to move part of the workload from the backend to the client. That’s when things start getting interesting.


One more thing

If you take a look at the repository, you might notice something important.

This is just a regular React app.

There’s no exotic architecture, no “from another planet” stack. Yes, there’s Rust compiled to WASM and there are WebGPU shaders — but they’re simply embedded into a standard frontend setup. The rest of the app looks exactly like something you could start in your project tomorrow.

That was intentional. I wanted to show that this isn’t some distant, experimental playground reserved for niche use cases. It’s something you can already integrate into real-world applications — incrementally, when you actually need it.

Of course, WebGPU is not yet universally supported, so you’ll need a fallback strategy. But at this point, for a large portion of users, there’s little reason not to start exploring it.


Final thought

The browser is no longer just a place where we render UI.

It’s a serious compute platform — one that already gives us access to both CPU and GPU, right out of the box.

You don’t need WebAssembly or WebGPU in every project. Most of the time, you’ll be perfectly fine without them.

But the moment you start hitting performance limits, or your problem shifts from “moving data around” to “actually computing things”… you might realize that the platform already had the solution all along.

And all you had to do was use it. 🚀

Top comments (13)

Collapse
 
pengeszikra profile image
Peter Vivo • Edited

Perfect demo! I love your work to seek the performance edge of the browser.
I feel the root of problem is language based. Because the WAT format is not really usefull for direct coding, so the WASM perfect soulution maybe a Rust, but I think worth to spend a time to create a better direct WASM text format, I started the work, but the mordorjs bit slow me down.

The other language is the SHADER which is much problematic to mastered, because whole GPU concept is totally different than a standard CPU based programming language logic. We are standing here the opening gate of threating AI ages, but even do not understand how we can controll our own machines.

For example a good example on a shader toy ( a great place to play with shader )
shadertoy.com/view/ffSSzW
if you take a look this is really hard to understand what is going on hardwer level compared to a simple assembley which is much more straight.
A few years ago I spend a lot of time on shadertoy but honestly right now I cannot able to wrtie a working SHADER code.

This is my minimal javascript shader bootstrap (without dependency - 8 years ago - as VibeArcheologist I have a lot of stuff in my past ):

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Thanks a lot for this comment, I really appreciate it 🙌

And yes, totally agree, understanding shaders is hard. It’s a completely different mental model compared to CPU programming, and it takes time to even start thinking in that way. I’m also really curious how this will evolve in the future. My gut feeling is that we won’t see average developers writing shaders directly, more likely we’ll rely on higher-level abstractions or libraries built on top of them.

I’ve actually been thinking about building a small POC around GPGPU myself, but before that I’d like to properly measure the performance, trade-offs, and whether it really makes sense in typical frontend scenarios.

Also, I’m curious, what’s your take on Zig for writing WASM? I haven’t tried it myself yet, but I’ve been hearing quite a lot of good things about it.

Collapse
 
moopet profile image
Ben Sinclair

I guess this only works on Chrome?

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Good question! 🙂
It works the same way as WebGPU support in general, so not just Chrome. It’s available in modern browsers like Firefox and Edge as well.
That said, WebGPU is still not a fully finalized standard yet, and there are some gaps, especially on mobile devices and certain environments like Linux. So we’re not quite at “works everywhere” yet.
But it’s definitely moving in that direction, it’s more a matter of time than anything else. That’s also why I mentioned in the article that having a fallback is still important for now 👍

Collapse
 
kamil7x profile image
Kamil Trusiak

I don't even try to switch to Canvas 2D tab 😂

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Haha no way 😄 almost 2.5 million particles and still decent FPS. That’s insane, this should totally be the cover photo 😂
And yeah… better not switch to Canvas 2D at that point, poor CPU wouldn’t survive that experiment 😅

Collapse
 
valentin_monteiro profile image
Valentin Monteiro • Edited

Excellent work on the demo, the JS WASM WebGPU pipeline really drives the point home.

The 2-3x WASM vs optimized JS benchmark highlights something we all do: we spend hours micro-optimizing code without ever questioning if the runtime itself is the right tool for the job. In data it's the same thing, you can spend 3 days tuning a SQL query when the real problem is you're running computation in the wrong place. The "I optimize what I know" reflex is comfortable but it's often what keeps you from seeing the actual solution.

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Exactly this! 🙌
It’s the same on the frontend, we often spend hours optimizing milliseconds, while here you can get a 2× gain with WASM and even 200–300× with WebGPU. That really puts things into perspective.
And sure, WebGPU isn’t fully supported everywhere yet, so you need to be mindful there. But WASM? That’s already widely available and production-ready, and still surprisingly underused for cases where it can make a real difference.

Collapse
 
harsh2644 profile image
Harsh

This is the kind of performance article we need more of practical, not theoretical.

The gap between works on my machine and works for users on 3G with a mid range phone is where most apps die. And it's not because developers are bad. It's because dev tools and local environments hide the slowness. Chrome DevTools on a MacBook Pro with fast internet tells you nothing about real user experience.

I've definitely been guilty of shipping something that felt fast to me, only to realize later that users were waiting seconds for things I didn't even notice.

The live demo approach is so valuable. Watching something be slow in real time hits different than reading about it.

What's the one performance issue you see most often in the wild that developers seem to ignore?

Thanks for this bookmarking. 🙌

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Thanks a lot, really appreciate it 🙌 and yes, exactly — these problems are very often ignored.

At least with DevTools we have some way to simulate slower network conditions and get a glimpse of what users might experience. Testing on weaker hardware is definitely harder though. That said, this is where things like WASM can actually help quite a bit, especially for heavier computations, because of its more predictable performance. And if you can push work to the GPU, even better — even a low-end GPU will usually handle parallel workloads much better than the CPU.

But overall, I still think the most commonly ignored performance issues are related to the network layer. In many small and mid-sized apps, it’s not the computation that hurts the most, but sending too much data, too often, and sometimes completely unnecessarily.

Collapse
 
nandofm profile image
Fernando Fornieles

I like your article but I like most the Text Goes Boom app, it's quite relaxing and just what I needed a few moments ago :-D

Collapse
 
sylwia-lask profile image
Sylwia Laskowska

Haha, right? 😄 I had the exact same experience, I even played with it for a moment during my talk just to relax a bit. Turns out “completely useless” apps can be surprisingly therapeutic 😄

Some comments may only be visible to logged-in visitors. Sign in to view all comments.