Hacker News new | ask | show | jobs
by mlsarecmg 1772 days ago
as absurd as it may seem to you, this is a react feature. the upcoming react 18 release is pretty much based on concurrency.

this is the test you are referring to: https://docs.pmnd.rs/react-three-fiber/advanced/scaling-perf...

the github repo now contains a vanilla test that you can run

1 comments

As I said, "schedule" just means "defer work to future frames". That's a valid strategy if you have severe load, but it's not globally applicable: one might imagine that two components need to be updated together (e.g. updating the arms and body of a character should not be split up between two frames, or else the user will see split bodies for in-between frames). At the very best, this sort of scheduling should be informed by gameplay systems.

It can "effortlessly outperform" only if we're talking about throughput, not latency here -- the scheduler ensures that less is done each frame so we can meet 60fps each frame, at the expense of having things done frames later than when they probably should have been.

I'm aware this is all a React feature. I disagree with the React team that "concurrency" is a usable solution to performance in all cases. But I can respectfully disagree with them about that. I can understand why a scheduler helps improve user-perceived performance. I'm happy to talk about what I believe are the tradeoffs.

Regardless of all of that, updating 2,000 cubes should never cause 700ms of load to begin with. The test you linked me to is not the same test. The test in the tweet is seen here [0], and has no artificial runtime delay as far as I can tell. For extra irony, note that they already have to bypass React (which is described as ItemSlow), in favor of the "Zustand approach", aka modifying things imperatively.

Remember, Three.JS is already running every frame, and rendering every frame, with or without a scheduler. That means that the 700ms overhead has to be coming from the React / R3F part of the demo.

[0] https://github.com/pmndrs/react-three-fiber/blob/e3a71baad42...

what you link there has more to do with react vs zustand.

if it interests you, read up on react 18 concurrency, this is the bit you are missing in this discussion.

No; that's not the test in question. The tweet I started the conversation with [0] shows a bunch of cubes, not text geometry. It's not the text geometry test. It's just creating and manipulating a bunch of cubes. Unfortunately, it was removed from the react-three-fiber examples, so it can't be easily run unless you check out an old version of the repo. It contains two switches, one for React vs. Zustand, and the other for Concurrency On vs. Off [1]. The tweet is talking about the concurrency mode.

I'm very familiar with React 18 concurrency, and gave my detailed analysis of it. The documentation you linked even confirms my analysis of it deferring work across frames:

> it can potentially defer load and heavy tasks

I've already given my feedback about that approach. I heavily suspect the overhead here is all React's reconciler / differ, as Svelte, which has no scheduler, performs similarly to the concurrent React mode[2].

[0] https://twitter.com/0xca0a/status/1199997552466288641 [1] See the description in the panel here. It's talking about React 18 concurrency. https://github.com/pmndrs/react-three-fiber/blob/e3a71baad42... [2] https://twitter.com/Rich_Harris/status/1200805237948325888

i've written them. the first pits react against zustand, it naively lets react churn through the whole graph 60 times per sec, you wouldn't do that ever, but zustand could. i initially tweeted it for people interested in that lib.

some got it in the wrong throat, so i changed the test to actually pit it against a vanilla counterpart, and they were silent. the real test, contest that please, let the zustand thing go.

Ah, so you're @0xca0a. Sorry, I didn't recognize you at first. The examples and documentation I'm quoting at you are your own; my mistake.

That said, I don't know why you entered into the conversation by asserting properties about a different test than the one that started the conversation. I recognize that TextGeometry is slow and CPU-heavy, and that the deferred work approach has some value in helping to manage that, but the cube test we started the discussion with had no artificial delay as far as I can tell, nor do I see it really doing any CPU-heavy work. For cases without any obvious CPU-heavy work, where does the 700ms overhead come from?

> and it stupidly and naively lets react churn through the whole graph 60fps, something you would under no circumstance do

Iterating over 2,000 objects is something we do all the time in game engines (where I'm from and where I work). I've written particle systems that handle far more than that; I just checked the particle system for a game I'm working on, and the simulation time maxes out at <1ms, and I haven't even SIMD'd it, though it is somewhat SoA'd. React's inability to handle a low workload like 2,000 items is why I believe React is a poor fit for serious 3D applications.

And yes, I would argue against React 18 Concurrency's approach as a general design. Deferring work between frames is an incredibly valuable tool, but I don't believe it's something that validly can be done globally, or that it's a solid basis for a 3D framework. It trades low latency for high throughput, and I believe that's a tradeoff that should be made by the application author.

Multiplayer games and VR often require very careful controlled latency, and having unpredictable latency can make your game unplayable, or make someone incredibly motion sick.

We're clearly going in circles on this point; I'll shut up at this point because clearly we're at an impasse, and you're (completely validly) unwilling to discuss the cubes example that started things, which I would prefer to cross-examine in more detail. My approach to performance analysis is to profile things, understand bottlenecks, and come up with targeted fixes before going with more global approaches with large tradeoffs, so I'd be personally be more interested in knowing where the time is spent.

Finally, and this is my experience speaking as a game engine engineer, I think you should think more about how much work you expect to be able to do in one frame, and set your sights there. You can easily update 2,000 objects with minimal overhead.

i am sorry but there is a deep misconception here. of course you can update thousands of things, why wouldn't you.

try racing game for instance: https://twitter.com/0xca0a/status/1400164834243719173

or space game: https://twitter.com/0xca0a/status/1184586883520761856

you won't find react in the browsers perf readout except for short blips when the tree structure is changed. you do not update fast things with setState. since games are render-loop driven, you mutate, and that is also how r3f works.

as for react 18, yes, it works global. the entire component tree is virtual and can be prioritized. you could say, this thing back there is less important than physics driving my rocket, defer please. this will be an incredible tool for games going forward.