Hacker News new | ask | show | jobs
by vbezhenar 254 days ago
I think that many projects use wrong architecture, when it's a possibility for business code to block animations.

IMO all the "user" code must run in a dedicated thread, completely decoupled from the rendering loop. This code can publish changes to a scene tree, performing changes, starting animations, and so on, but these changes ultimately are asynchronous. You want to delete an element from a webpage, but it'll not be deleted at this JS line, it'll be deleted at the next frame, or may be after that, if rendering thread is a bit busy right now.

Animations must stay fluid and UI must react to the user input instantly. FPS must not drop.

Browser does it wrong. Android GUI API does it wrong. World of Warcraft addons do it wrong.

6 comments

Which begs the question - if all of these projects got it "wrong", what's the chance that the "right" thing isn't right at all?

All animation is inherently discrete. No matter how many threads you have, there always has to be the last rendering thread, the thing that actually prepares the calls to the rendering backend. It always has to have frames, and in every frame, in the timestamp T, it will be interested in getting the world state in the timestamp T. So, the things that work on the world state - they have to prepare it as it was in T, not earlier, not later. You cannot completely decouple it.

In one of game projects that I worked on, a physics thread and a game thread actually were pretty decoupled, and what the game thread did was extrapolating the world state from the information provided by physics, because it knew not only the positions of physics objects, but also their velocities. Can we make every web developer to set velocities to the HTML elements explicitly? Probably not.

This has been tried, even in the browser. It just leads to buttons that do nothing when clicked, scrolling to unpopulated areas, infinite loading animations and other such artifacts.

It does not help, you have smooth animations but you feel you're disconnected from the program and trust it less. The UI code just needs to not take much time and offload background stuff to another thread, but not the UI logic itself. It also naturally synchronizes events.

And sometimes it's better to briefly block UI thread as the alternatives lead to worse user experience.

I still feel these issues could be solved one by one.

Button click will automatically disable it, until its handler executed. There could be creative animations translating this state to the user in an intuitive way, so the button does not feel stuck and does not feel doing nothing.

Scroll widget should require some placeholder graphics which will be displayed until loading handler executed and replaced this placeholder with real data. A lot of apps already do exactly that.

That's basically what React Native does/did and it's generally good but turns into a nightmare when you need to synchronize interactions between the two threads. 16ms is a long time - if your UI manipulations eat up most of that time then there's something wrong. Entire video games can run basically on one thread within that time and they do way more.
16ms is a long time by C standards.

16ms is not a long time, when interpreted languages like Lua are used.

16ms is not a long time, when GC can suddenly kick in and stop the thread for unspecified amount of time.

16ms is not a long time, when JIT can suddenly kick in and stop the thread for unspecified amount of time.

GC and JIT are good techniques for server-style throughput workloads, when infrequent delays are not noticeable. For GUI, infrequent delays lead to skipped frames and stuttering.

I don't think that it's reasonable to ask the world to develop GUI apps in C or Rust. Probably Swift is a good middle point between usability and predictable performance. But most GUI projects use slow languages and/or languages with GC.

I disagree. Yes, it's less time vs. C but still a long time.

There are plenty of games built with Lua that run very well such as Balatro and Don't Starve. And games are far more sensitive to hitches than GUI projects because they are constantly animating. Your users will not only easily see lag - it can ruin the game for them.

If a basic GUI is performing poorly then the blame almost certainly lies on whoever developed it. Don't blame the language or runtime.

I’ve only ever seen competitive video games get the architecture right. They have the natural incentive of needing stable high FPS.

Random GUI apps aren’t incentivized enough and so garbage leaks through. I die a bit every time a random GUI app stutters drawing 2D boxes

Multithreading in the browser kinda sucks though, it's too slow to share significant data between workers (threads), and if you try it with SharedArrayBuffer you eat the serialisation costs.
Not really something anyone can change at this point, given that the entire web API presumes an execution model where everything logically happens on the main thread (and code can and does expect to observe those state changes synchronously).