How could BodyNodeSlot's performance be improved? #3927
Replies: 5 comments 4 replies
-
|
Esnya's metrics profiler mod is great, I love it and use it all the time. However, the mod does not profile the entire process of generating a frame, and cannot always give a fully accurate measurement as to how performant something is. I would be very curious as to how much fps you gain/lose when deleting and spawning the example you show. (saying this early on because there have been misconceptions about this in the past) Additionally, reproduction avatars/systems could help a lot if you have access to them. Based off of the numbers shown on the profiler, your frame times could be improved by ~.4ms, which might equal a 1fps improvement. However, you do mention that this has been the cause of significant frame loss in the past, so I can't say conclusively how much of an issue this is. While it could be argued that it is the users job to store the result of this node, there may be a way to allow it to automatically cache and refresh its result, though I am not sure if this goes against the spirit of continuously changing flux nodes. I might try to make a mod that automatically caches the result of this node and skips the search. I'll report back if I end up doing it, along with whether or not it helped performance significantly. |
Beta Was this translation helpful? Give feedback.
-
|
I've been looking into how values can be cached with flux. If the flux happens to be part of an tool or avatar then you can detect when the active user changes and update the cached value which is often good enough. For instances that are used outside of the UserRoot like the one I initially showed it I'm having trouble finding a consistent and reliable way to determine when the slot may change. In both instances there enough avatars with dynamically equippable body nodes where I'm not sure how to check for slot changes like that in a trivial way. |
Beta Was this translation helpful? Give feedback.
-
|
Setting aside the possibility of an under-the-hood technical improvement to this, I think this really comes down to user knowledge / education. It's been generally known for a long time that certain operations can be comparatively expensive (e.g. FindChildByName or SampleColor). If you find nodes like BodyNodeSlot which seem to have an unexpectedly large impact you could make a note on the Wiki, perhaps on the node's page and/or on https://wiki.resonite.com/Optimization_Guidelines, and try to spread the information around. It'll make it's way through the community eventually. The point you make about manually caching values from nodes where possible is also good - I do this quite often. I guess some users may try to avoid that based on misunderstandings about the performance costs re: writes vs. drives? Another point, if users are simply looking for slots or positions of common avatar parts (e.g. head, hands, feet) there are some nodes under Users > UserRoot which can provide those without needing to use BodyNodeSlot at all. |
Beta Was this translation helpful? Give feedback.
-
|
Encountered this again and had to explain why it's so laggy to a user, and still have not found a good way to cache it robustly if it's not parented under the user. It feels very unintuitive that it has a worse case complexity like it does. My current thought and suggestion currently is to make |
Beta Was this translation helpful? Give feedback.
-
|
I haven't had time to look into this depth, but generally there's one problem with caching - when/how do you invalidate the cache? While this speeds up the lookup of things, it risks altering the behavior of the node, especially when things change. For example a following sequence can occur:
I'd have to poke into things to see if this would be easy or not, but it's one of the issues that I feel is often forgotten about - cache invalidation tends to be one of the biggest three issues in programming x3 With user-side caching, the caching itself can be structured to work with given user logic, but doing a general caching cannot make any assumptions. |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I wasn't really sure whether to make an issue or discussion for this but a discussion seemed better since it's intended behavior and not really an issue outside of "BodyNodeSlot is laggy with how it's commonly used", and how to improve it may need discussion if it involves changing the current behavior of it. Please direct me towards creating an issue if this is incorrect.
The BodyNodeSlot node currently functions by going through every slot and component looking for a bone that matches the BodyNode. This has a worst case of searching every single slot + component on the user root looking for one that matches.
When paired with a continuously updating flux group it can eat away at performance innocuously because it does not seem like it should be that heavy. It can be hard to notice because one avatar may have a best case early exit while another may not even have a matching body node and will have worst case performance.
There have been two instances where I investigated performance in a world when trying to improve it and all of the fps loss was from a worst case BodyNodeSlot in an avatar with a lot of slots. Storing the result helped but it required knowledge about this non-obvious behavior first.
Recently I've started using https://github.com/esnya/ResoniteMetricsCounter, and what's immediately jumped out at me is how many instances of BodyNodeSlot are being used in continuous groups across random avatars/objects, leading to those flux groups often being towards the top of the chart.
VRIK and other heavy components/patterns are still (generally) heavier than a single BodyNodeSlot with a non worst case search, but it still adds up. I've also found BodyNodeSlot is usually paired with another one for chirality reasons, compounding the issue.
What this discussion is about is a question of how the performance of the node can be improved without requiring rewriting all previous flux that uses it, and how new flux can avoid those issues as long as performance remains poor.
Here's an example of one instance I found that was very simple and had poor performance.
Beta Was this translation helpful? Give feedback.
All reactions