You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So I've been tracking down why calling functions like void fun(PackedFloat32Array& array) with PackedFloat32Array args makes a copy for every argument before calling the function. This is mostly unnoticeable, except for small speed losses because of conversions / copies, as well as the inability to modify the given object in-place.
I believe the crux lies in VariantCasterAndValidate (and similar), which always return T copies when given Variant objects as parameters. I believe this is the case when calling from GDScript.
Just for tests, I modified the code to return T& when possible, and I believe it works - but it does come at the cost of automatic conversions. e.g. when a function is currently expecting PackedFloat32Array, but is given an array (within a Variant), the array is converted by VariantCasterAndValidate to Array automatically, and the function is called with a reference to the copy.
My thoughts are, for the interface that's nonsense; if a copy is made anyway it should just be made explicit by the function interface, and if a reference is expected, it makes sense to abort the call if the argument cannot proceed without conversions. But some functions are created are created to be called from both GDScript and C++, and changing the parameter to take a copy would not make sense in C++ (because that would introduce more copies to be made).
The final option would be to only copy those parameters that need a copy, and pass the reference down otherwise. But that would complicate the code, because the function cannot return a copy or lvalue based on runtime information.
I can't think of any other solutions, so we may have to live with lvalue references still causing copies to be made for every single argument it receives. Godot types are all optimized to be fast copiers (being either small or COW), so it's not a tragedy, but it still leaves this weird situation unsolved (for me anyway)...
I'm posting this to document my current findings; open to comments and suggestions. You can find the needed changes for conversion-disabling lvalue arguments here: Ivorforce/godot@64e3d5e
(notice especially the failing unit tests because of failed conversions)
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
So I've been tracking down why calling functions like
void fun(PackedFloat32Array& array)
withPackedFloat32Array
args makes a copy for every argument before calling the function. This is mostly unnoticeable, except for small speed losses because of conversions / copies, as well as the inability to modify the given object in-place.I believe the crux lies in VariantCasterAndValidate (and similar), which always return
T
copies when givenVariant
objects as parameters. I believe this is the case when calling from GDScript.Just for tests, I modified the code to return T& when possible, and I believe it works - but it does come at the cost of automatic conversions. e.g. when a function is currently expecting
PackedFloat32Array
, but is given an array (within aVariant
), the array is converted byVariantCasterAndValidate
toArray
automatically, and the function is called with a reference to the copy.My thoughts are, for the interface that's nonsense; if a copy is made anyway it should just be made explicit by the function interface, and if a reference is expected, it makes sense to abort the call if the argument cannot proceed without conversions. But some functions are created are created to be called from both GDScript and C++, and changing the parameter to take a copy would not make sense in C++ (because that would introduce more copies to be made).
The final option would be to only copy those parameters that need a copy, and pass the reference down otherwise. But that would complicate the code, because the function cannot return a copy or lvalue based on runtime information.
I can't think of any other solutions, so we may have to live with lvalue references still causing copies to be made for every single argument it receives. Godot types are all optimized to be fast copiers (being either small or COW), so it's not a tragedy, but it still leaves this weird situation unsolved (for me anyway)...
I'm posting this to document my current findings; open to comments and suggestions. You can find the needed changes for conversion-disabling lvalue arguments here: Ivorforce/godot@64e3d5e
(notice especially the failing unit tests because of failed conversions)
Beta Was this translation helpful? Give feedback.
All reactions