On ABZÛ we ripped out multiplayer and lots of other cruft from AActor and UPrimitiveComponent - dropping builtin overlap events, which are a kind of anti pattern anyway, not only saved RAM but cut a lot of ghost reads/writes.
Whoa! Didn't picture myself seeing a dev who worked on Abzu in the wild here on HN--I very much enjoyed that game, my thanks and high fives to your team for your work!
I'm having a kid-in-the-tunnel-meeting-Mean-Joe-Green-in-the-commercial moment, I just started my own game development journey about a week ago so it's neat getting to run across a full-on developer!
To stay on topic, I often thought how cool Abzu would have been with multiplayer but it's a good lesson to me that some features that might be desirable might also be a hindrance to some degree.
Oh, nice to see that there are real-life examples of this stuff, thank you very much :)
Needless to say that I'll take a deeper look at the overlaps now :D
In principle it's a fine idea, but their implementation has so many footguns (race conditions, thundering herds, perf cliffs, etc) it was easier to impl your own simpler alternative.
Your presence inspired me to try to look up what the circumflex on "abzû" is supposed to signify. As best I can tell, it's a marker of vowel length.
I wonder how that came to be used. It's a traditional way to distinguish eta and omega in transliteration from Greek, but it's not at all a traditional way to mark long vowels in general.
(I see that wikipedia says this about Akkadian:
> Long vowels are transliterated with a macron (ā, ē, ī, ū) or a circumflex (â, ê, î, û), the latter being used for long vowels arising from the contraction of vowels in hiatus.
But it seems odd for an independent root to contain a contracted double vowel. And the page "Abzu" has the circumflex on the Sumerian transliteration too.)
You would probably want to avoid having tens of thousands or a hundred thousand actors though, they're pretty heavy regardless. There might be a few reasons why you'd want to have that many but I think ideally you'd want to instance them or have some kind of actor that handles UObjects instead
Depending on a bunch of factors of how this data is accessed and actors are laid out in memory, it may be more cache friendly which could yield substantial speedups.
Or it could do next to nothing, as the data is multiple cache lines long anyway.
If the memory savings he got were fully read or fragmented with other stuff on cache lines that are read in every frame (not likely for static world actors), it could be ~10% of CPU memory bandwidth on mobile every frame at 120hz on an lpddr4 phone.
A big problem with them is they are so heavyweight you can only spawn a few per frame before causing hitches and have to have pools or instancing to manage things like bullets.
I think in their Robo Recall talk they found they could only spawn 10-20 projectile style bullets per frame before running into hitches, and switched to pools and recycling them.
Pooling is pretty standard practice though, it would be the go-to solution for any experienced gameplay programmer when dealing with more than a dozen entities (though annoyingly there isn’t a standardised way of doing it in Blueprint).
To be completely fair though, blueprints themselves are oft-maligned for performance.
They're fantastic for prototyping, but once you have designed some kind of hot-path most people typically start converting blueprints to code as an optimisation.
In such a scenario adding pooling becomes a trivial part of such an effort.
This attitude comes up on here whenever gamedev comes up, and I really dislike it.
Here's a quote form the article
> I’ve already told you that this method saves 328 bytes per actor, which is not too much at first glance. You can apply the same trick for SceneComponents and save another 32 bytes per SceneComponent. Assuming an average of two SceneComponents per actor, you get up to 392 bytes per actor. Still not an impressive number unless you deal with a lot of actors. A hypothetical example level with 25 000 actors (which is a lot, but not unreasonable) will save about 10 MB.
I've a lot of experience with Unreal, and 25k actors is likely to run into a whole host of problems, such that saving 10MB of RAM is likely to be the least of your worries. You'd get more benefit out of removing a single unneeded texture, or compressing a single animation better.
One of the reasons developers use unreal (and yes, developers do use Unreal, it's not just "big companies" forcing their poor creatives to use the engine) is _because_ unreal has more man hours of development in a year than a small team would ever be able to put into their own engine. Like any tool it has tradeoffs, and it does have a (measureable) overhead. But to say that companies don't care is just disingenuous
I haven't profiled this specifically, but my guess is that there shouldn't be any measurable performance gains. Most of the time, actors are randomly scattered in memory anyway, so having smaller actors doesn't avoid a lot of cache misses.
The actors in unreal are such bloated single inheritance god classes that with a few actor components they take up more like a 4K memory page not part of a cache line, especially in editor builds.
But they do have a more optimized entity component system now too.
To be fair, a single transform now that things are 64 bit coordinates I think is bigger than a cache line too.
Oh, good point. The test was done in the current stable 5.5 release in a development configuration :)
Since this is a change to the memory layout of the class, there should be no change due to the build configuration, though.
On ABZÛ we ripped out multiplayer and lots of other cruft from AActor and UPrimitiveComponent - dropping builtin overlap events, which are a kind of anti pattern anyway, not only saved RAM but cut a lot of ghost reads/writes.
Whoa! Didn't picture myself seeing a dev who worked on Abzu in the wild here on HN--I very much enjoyed that game, my thanks and high fives to your team for your work!
I'm having a kid-in-the-tunnel-meeting-Mean-Joe-Green-in-the-commercial moment, I just started my own game development journey about a week ago so it's neat getting to run across a full-on developer!
To stay on topic, I often thought how cool Abzu would have been with multiplayer but it's a good lesson to me that some features that might be desirable might also be a hindrance to some degree.
Okay, enough fanboying!
Oh, nice to see that there are real-life examples of this stuff, thank you very much :) Needless to say that I'll take a deeper look at the overlaps now :D
What makes overlap events an anti-pattern?
In principle it's a fine idea, but their implementation has so many footguns (race conditions, thundering herds, perf cliffs, etc) it was easier to impl your own simpler alternative.
Your presence inspired me to try to look up what the circumflex on "abzû" is supposed to signify. As best I can tell, it's a marker of vowel length.
I wonder how that came to be used. It's a traditional way to distinguish eta and omega in transliteration from Greek, but it's not at all a traditional way to mark long vowels in general.
(I see that wikipedia says this about Akkadian:
> Long vowels are transliterated with a macron (ā, ē, ī, ū) or a circumflex (â, ê, î, û), the latter being used for long vowels arising from the contraction of vowels in hiatus.
But it seems odd for an independent root to contain a contracted double vowel. And the page "Abzu" has the circumflex on the Sumerian transliteration too.)
"Abzu" is also the Greek onomatopoeia for a sneeze.
I was highly amused to learn that the ancient Greek verb for spitting is πτύω. (Compare English "ptooey".)
Yeah, and the modern is much the same ("φτύνω"). I'm sure it's onomatopoeic, and it's an amusing word.
Does the popular 'hawk' prefix for this also originate from ancient Greek ?
You would probably want to avoid having tens of thousands or a hundred thousand actors though, they're pretty heavy regardless. There might be a few reasons why you'd want to have that many but I think ideally you'd want to instance them or have some kind of actor that handles UObjects instead
Really interesting analysis of where the data lives… cutting 3-4 textures would save you more memory even in the 100k actor case, though.
Depending on a bunch of factors of how this data is accessed and actors are laid out in memory, it may be more cache friendly which could yield substantial speedups.
Or it could do next to nothing, as the data is multiple cache lines long anyway.
If the memory savings he got were fully read or fragmented with other stuff on cache lines that are read in every frame (not likely for static world actors), it could be ~10% of CPU memory bandwidth on mobile every frame at 120hz on an lpddr4 phone.
A big problem with them is they are so heavyweight you can only spawn a few per frame before causing hitches and have to have pools or instancing to manage things like bullets.
I think in their Robo Recall talk they found they could only spawn 10-20 projectile style bullets per frame before running into hitches, and switched to pools and recycling them.
Pooling is pretty standard practice though, it would be the go-to solution for any experienced gameplay programmer when dealing with more than a dozen entities (though annoyingly there isn’t a standardised way of doing it in Blueprint).
To be completely fair though, blueprints themselves are oft-maligned for performance.
They're fantastic for prototyping, but once you have designed some kind of hot-path most people typically start converting blueprints to code as an optimisation.
In such a scenario adding pooling becomes a trivial part of such an effort.
Too bad big companies don't care about this and more. "Morons(gamers) will just buy new hardware, fu hiring engine core devs".
This attitude comes up on here whenever gamedev comes up, and I really dislike it.
Here's a quote form the article
> I’ve already told you that this method saves 328 bytes per actor, which is not too much at first glance. You can apply the same trick for SceneComponents and save another 32 bytes per SceneComponent. Assuming an average of two SceneComponents per actor, you get up to 392 bytes per actor. Still not an impressive number unless you deal with a lot of actors. A hypothetical example level with 25 000 actors (which is a lot, but not unreasonable) will save about 10 MB.
I've a lot of experience with Unreal, and 25k actors is likely to run into a whole host of problems, such that saving 10MB of RAM is likely to be the least of your worries. You'd get more benefit out of removing a single unneeded texture, or compressing a single animation better.
One of the reasons developers use unreal (and yes, developers do use Unreal, it's not just "big companies" forcing their poor creatives to use the engine) is _because_ unreal has more man hours of development in a year than a small team would ever be able to put into their own engine. Like any tool it has tradeoffs, and it does have a (measureable) overhead. But to say that companies don't care is just disingenuous
[dead]
Besides the memory savings, would there also be performance gains? More actors would now fit in a cache line.
I haven't profiled this specifically, but my guess is that there shouldn't be any measurable performance gains. Most of the time, actors are randomly scattered in memory anyway, so having smaller actors doesn't avoid a lot of cache misses.
The actors in unreal are such bloated single inheritance god classes that with a few actor components they take up more like a 4K memory page not part of a cache line, especially in editor builds.
But they do have a more optimized entity component system now too.
To be fair, a single transform now that things are 64 bit coordinates I think is bigger than a cache line too.
is it me or does the side loop endlessly loading thousands of requests? to at least:
- https://public-api.wordpress.com/wp-admin/rest-proxy/#https:...
- https://s0.wp.com/wp-content/js/rlt-proxy.js?m=20240709
blocking these via regex made the page load up really nice and fast
edit: formatting
Would this have any effect in prod build though?
That was my immediate thought on reading the article. Is this in dev or prod builds and which UE version is it referring to?
(Not that I expect the UActor code to have changed much but modifying UActor seemed more common in the early 4.x days.)
Oh, good point. The test was done in the current stable 5.5 release in a development configuration :) Since this is a change to the memory layout of the class, there should be no change due to the build configuration, though.