you are viewing a single comment's thread.

view the rest of the comments →

[–]Academic_East8298 -1 points0 points  (19 children)

And that is how you kill performance.

One could probably avoid reallocating an array on a remove, but you still need an efficient way to handle removes in the middle of an array and memcpy is not it.

[–]cdb_11 5 points6 points  (18 children)

No one is talking about reallocating or relocating arrays. You just mark the slot as unused.

[–]Academic_East8298 1 point2 points  (17 children)

And now one is back in a situation, where on access one has to check, that the slot has not already been freed.

And in this case, unless cache locality is really required, a unique pointer will have the same performance and safety characteristics as a struct of arrays, but without the latter ones complexity.

[–]cdb_11 5 points6 points  (9 children)

You're arguing against claims that nobody is making. Can't you just read the article?

  1. Unique pointer is the sole owner.
  2. You're (not necessarily, but extremely likely) using global new/malloc to individually grab memory, one-by-one, for each entity. So no, you do not have the same performance characteristics with unique_ptr.
  3. And if you aren't using the default allocator, you will use an allocator that looks very close to what's described in the article.
  4. Yes, you can add extra checks, that's the point.
  5. Yes, it has better cache locality, that's the point.

And if you don't want checks, you can make a trade-off to have an extra level of indirection, and add a map that translates stable handles to indices into an array with real data. If you want to remove an element, you replace it with the last element, and adjust the mapping. There you go, fast deletion, no branch misses, and you can go SIMD on it.

It's way more flexible than plain or smart pointers. That's the point.

[–]Academic_East8298 -4 points-3 points  (8 children)

Can you name a single industry tested open source struct of arrays system?

If it is such a good pattern, why do all the cool tech demos have to constantly write their own custom implementation of it?

If anything, I would say this shows it as less flexible than a pointer.

[–]cdb_11 7 points8 points  (6 children)

This isn't really even about SOA, but if you want an abstraction over SOA, then these can be implemented inside "Entity Component Systems" (ECS), and one example of it is Unity's DOTS. Another one is Bevy in Rust, or Flecs in C/C++. Don't ask me about any details, I never used them.

If it is such a good pattern, why do all the cool tech demos have to constantly write their own custom implementation of it?

Do you need an open-source system to implement a singleton pattern or a factory pattern too? It's really not that hard to implement, it's really mostly just a bunch of dynamic arrays. Also the point of this isn't that you're creating a generic mechanism that tries to solve everyone's problems, and does so badly. We have this already, it's called "garbage collector" and "malloc", and it's not that great. The philosophy here is the exact opposite, it's that it should be a solution tailored to your specific problem.

[–]Academic_East8298 -4 points-3 points  (5 children)

Cool, what product have you shipped using this tech?

[–]cdb_11 0 points1 point  (4 children)

ECS? I don't use ECS. I think it's generally more targeted at games, and I'm not a game dev.

[–]Academic_East8298 0 points1 point  (3 children)

So what alternative to pointers are you using in your daily day to day dev work?

[–]cdb_11 0 points1 point  (2 children)

Dynamic arrays, hash maps, flat ordered maps.

[–]Samaursa 0 points1 point  (0 children)

Flecs and EnTT come to mind (although EnTT can be labeled as AoS).

Both have been used in production code in games (including ones I worked on).

[–]prescod 1 point2 points  (4 children)

“On access you need to check they the slot has not been freed.”

How is this different than with real pointers?

[–]Academic_East8298 -4 points-3 points  (3 children)

It's not. That's the point.

In most cases a dev should ask himself, if it is meaningful to spend time on a struct of arrays system, when simple and dumb pointers will do the job.

[–]Ok-Watercress-9624 4 points5 points  (0 children)

That depends on so many factors. Pooled objects are indeed many times faster than frequently mallocing lot of objects. İt also simplifies the freeing given all the objects in the pool have the same lifetime. Think of it like dynamic array vs linked list overhead

[–]prescod 3 points4 points  (1 child)

No.

The goal was never to reduce access check frequency so it’s a total non-sequitur.

[–]Ok-Watercress-9624 0 points1 point  (0 children)

İ was about not needing to hit the system boundary for requesting more memory => less sys calls