4 ms·
The reason OOP kills cache locality and multithreading opportunities is walking the object graph depth-first through nested method calls and pointers. Doesn't
by ajuc 5y ago
The reason OOP kills cache locality and multithreading opportunities is walking the object graph depth-first through nested method calls and pointers.
Doesn't matter if it's car.drive() referencing driver through a private pointer or driver.drive(Car c) calling methods on Car through the provided parameter - in both cases you will jump from class Car to Driver and back and then again for the next car and the next driver.
In real life the callstack is rarely 2-levels deep - I've seen stacktraces that had hundreds of levels. So your code will jump 100 levels down then 10 levels up then another 10 levels down, and so on, and then finally back up through 100 levels of nesting only to advance to the next top-level object and do the whole ceremony again for each of them :) It boggles the mind when you think about it :)
When the object graph is big enough and doesn't completely fit in cache this slows the code by orders of magnitude each time you jump through the border.
And because dependencies are implicit and execution order is accidental (and programmer doesn't actually know what other execution orders would be correct) - you cannot easily parallelize that code.
The alternative is to specify the dependencies explicitly, split the data according to functions that use it not according to metaphysical Classes where it belongs and walk the data graph in levels - starting from the level that doesn't depend on any other code being run, completing the level first then going to the level that now has all dependencies satisfied, and so on.
Of course there might be cycles that require special treatment, but at least they are explicit so you won't introduce them unless you actually have to.
End result is basically "relational programming". In case of gamedev it's called Entity Component System.
- mytailorisrich 5y agoThe point I'm trying to make is that OO design principles are one thing, how these are implemented by various systems or languages is quite another. OOP does not kill cache locality for the simple reason that these are orthogonal concepts. > split the data according to functions that use it not according to metaphysical Classes where it belongs Well, of course and as mentioned, picking the best model, and thus the best object representation, for the job is paramount. I read "split the data according to functions that use it" as "come up with objects that make the most sense for what you're trying to achieve", not "forget about OO design".