Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The issue is that while this greatly simplifies the program logic, when you start to scale the application you do end up with a lot of redundant computation. So in the end you need to either:

. take a performance hit

. somehow track/update costly intermediaries in your global state, and this can balloon out of control really fast

. pair it with some memoization mechanism/framework that automatically manages "derived state" variables



Yup, and I strongly suggest option 1, just take the perf loss. You can probably detect in each of your state update functions that nothing changed and just reuse the previous result (a memcpy is pretty fast, or if that data is in a separate allocation just copy the pointer).

The same is true of the functional core idea really, you're still going to have a big tree of function calls rebuilding things unless you also add some memoization to it. React and friends do it because DOM manipulation is very slow.

But think of IMGUI style GUIs, they're rebuilding the entire user interface every frame and yet are often more efficient than many retained mode UIs. Redundant computation is not as bad as it sounds at first glance.


I asked around and there is another option. Something called "Incremental Computations". Here is a Clojure library. I think the examples kinda demo how it works

https://github.com/hoplon/javelin

It's sort of a version of option 3


> and yet are often more efficient than many retained mode UIs

I don’t know what metric you use for that, but they are definitely not more energy efficient — retained mode is a must for any battery-powered device.


I meant computational efficiency, highly dynamic UIs usually perform a lot better as immediate mode GUIs since there are less indirections and memory allocations going around.

If you're rebuilding things a lot anyway, it's actually more efficient to just accept that rather than work around it.

Though speaking of immediate mode UIs, I think a lot of the problem there is that most of the immediate mode UI libraries assume they're being used as the user interface of a Game or 3D render application which needs to render a complex 3D scene regardless, so who cares about the extra 400 microseconds the UI takes to render.

You could imagine optimizing immediate mode UIs quite a bit for energy efficiency by not redrawing anything if there's no use input, or selectively redrawing dirty areas where it makes sense.


> You could imagine optimizing immediate mode UIs quite a bit for energy efficiency by not redrawing anything if there's no use input, or selectively redrawing dirty areas where it makes sense.

That’s pretty much what a retained-mode UI does.


I don't mean doing it in a retained-mode-like way with a data structure in memory, I mean special casing certain UI elements. For example, a blinking cursor could be a special path through the code which updates only the pixels where the blinking cursor is, while the rest of the window just reuses the last drawn frame (kinda like how mouse cursors are handled in hardware). Similar tricks work for things like hover highlights and context menus.

No need for a retained data structure to implement the above.


On the other hand, I've found that a lot of the caching that happens organically from each component building up it's own state of the world can lead to poor performance of its own. You often end up reading single values from random places in memory.

You can often optimize a single, large state transformation by utilizing that it does a lot of similiar work. You can also often get a big performance boost by batching up computations.

Half of all performance problems are solved by introducing a cache. The other half is solved by removing one.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: