Avoid unnecessary copies of container types - #110912
Conversation
| * find an element in the list, | ||
| */ | ||
| template <typename T_v> | ||
| const Element *find(const T_v &p_val) const { |
There was a problem hiding this comment.
I added a const version of List::find to support using find in const contexts.
|
|
||
| HashMap<Vector2i, TileMapCell> err_output; | ||
| ERR_FAIL_COND_V(pattern->is_empty(), err_output); | ||
| ERR_FAIL_COND_V(pattern->is_empty(), (HashMap<Vector2i, TileMapCell>())); |
There was a problem hiding this comment.
Yes, this was a copy before. I assume this was done as a separate variable to avoid the problem of commas inside macros, but there is a solution: Wrap the macro arguments in parenthesis. So in this case, the value returned by this error macro is (HashMap<Vector2i, TileMapCell>()).
I'm not seeing this change, did you push this? |
|
@Ivorforce No, please see the part of the PR description where I wrote "and return the copy constructors to normal". It's a list of things I did in order, not a list of the final changes in the PR, sorry for the confusion. |
Aha, makes sense. Why did you return the constructors to implicit after your fixes? |
|
@Ivorforce Because the rest of the changes span 100 files and I want to separate them for improved reviewability. The existing codebase of Godot has many places where implicit copy constructor is used, which all had to be changed. |
|
Alright, that makes sense. Thanks for clearing that up! |
There was a problem hiding this comment.
This is a great effort. Those implicit copies keep haunting us, and we really should be getting rid of them.
Unfortunately, this change is not without risk. Taking a reference instead of making a copy makes the caller vulnerable to changes during execution of the code that uses these variables. If the underlying data is modified, this could lead to crashes, data corruption, or subtle bugs.
Since this change is motivated and informed by a syntactical change (making the constructors explicit), rather than a profiler, I think there's too much risk of regression to make this a blanket change. I might be swayed if you go through all of the code, and make absolutely sure there is no risk of mutation regressions, but I'm not sure if this is worth it (since we don't know if any of this is in performance critical code).
If I were to make this change, I would simply make the call explicit syntactically (via e.g. List(other_list)), to keep the syntactic change agnostic to possible changes in behavior. If the code pops up in a profiler in the future, it can more easily be fixed, because the copy is explicit and therefore an obvious target for optimization.
|
@Ivorforce That's why I think such a change should be done early in the dev cycle, to increase the chances that any problems are caught before a release happens. Since 4.5 was just released, we have plenty of time to test before 4.6. |
That's true, but I personally wouldn't feel comfortable risking regressions over this without any tangible benefit (i.e. profiling or benchmarking performance improvements). |
|
@Ivorforce Understandable, but then I am left stuck between a rock and a hard place:
This really just leads me back to option 1 again, adding the duplicate function without deleting the copy constructors, which is risk-free (unlike this PR) and does not destroy the intent of existing code (unlike blanket changing everything). I can update PR #107377 to add this to the rest of the container types if this is desired. Alternatively, I would be happy with whatever course of action you propose, if you would like to make a PR yourself. |
41dc86d to
fad5d8f
Compare
fad5d8f to
e398fc5
Compare
e398fc5 to
b729ac1
Compare
b729ac1 to
7a91348
Compare
7a91348 to
2fe2f4b
Compare
2fe2f4b to
0d33bb3
Compare
0d33bb3 to
234192c
Compare
234192c to
d9a1bfc
Compare
d9a1bfc to
c05e9e8
Compare
c05e9e8 to
043c51d
Compare
043c51d to
e84f279
Compare
This PR was made by doing the following:
This PR changes behavior by avoiding copies, which should only improve performance with no negative consequences. For each change I checked if it was good. However, it is perfectly possible that I made mistakes.
After this PR, we can follow-up with either making the copy constructor explicit or adding
duplicate, see the discussion in PR #107377 for more information.