Reuse/optimize common OperatorEvaluator*::evaluate logic#113132
Reuse/optimize common OperatorEvaluator*::evaluate logic#113132akien-mga merged 1 commit intogodotengine:masterfrom
OperatorEvaluator*::evaluate logic#113132Conversation
There was a problem hiding this comment.
Looks great! I was really hoping this would be refactored some time, so I'm grateful you are taking care of this.
The code makes sense and looks good to me. I'm actually surprised it makes this much of a difference!
I've got just one comment where I think we should be able to squeeze out some more performance.
Added CommonEvaluate class to be used by OperatorEvaluator* classes that have the same logic for `evaluate` and `validated_evaluate`. CommonEvaluate initializes the return Variant to the correct type, then passes through to validated_evaluate, reducing code duplication between evaluate/validated_evaluate and avoiding the overhead of creating/destroying temporary Variants from previous evaluate implementations.
d4a55a2 to
5f7566a
Compare
There was a problem hiding this comment.
Looks great to me!
I benchmarked with your tests as well.
The improvement is not nearly as good for me as it is for you (did you benchmark an unoptimized build perhaps?), but the improvement is consistent, and what I'm measuring is more along the lines of what I would expect from this kind of change too. (I hope my latest proposed change isn't what broke it though! 😅 Edit: Seems not to be the case :) )
master (235a32ad11f40ecba26d6d9ceea8ab245c13adb0)
sort_int : 161ms
sort_str : 265ms
min_max : 183ms
sum_int : 299ms
sum_float : 357ms
sort_dict : 94ms
this pr (5f7566a72ec265335b006a337287b976fd77e3fd)
sort_int : 130ms
sort_str : 242ms
min_max : 143ms
sum_int : 301ms
sum_float : 340ms
sort_dict : 84ms
this pr, earlier state (d4a55a2206a2c8721d49794f2d1124f419d3286f)
sort_int : 128ms
sort_str : 242ms
min_max : 142ms
sum_int : 300ms
sum_float : 340ms
sort_dict : 86ms
Sorry, should have mentioned in my last comment, I compared with I built with |
The most prominent optimization option would be |
|
Thanks! |
Added
CommonEvaluateclass to be used byOperatorEvaluator*classes that have the same logic forevaluateandvalidated_evaluate.CommonEvaluateinitializes the returnVariantto the correct type, then passes through tovalidated_evaluate, reducing code duplication betweenevaluate/validated_evaluateand avoiding the overhead of creating/destroying temporaryVariants from previousevaluateimplementations.The main performance benefit from this change is for methods that call
Variant::evaluatedirectly, such assortandmin/maxmethods. GDScript handling of operators already has some optimizations to useVariantInternal::initialize/validated_evaluateinstead ofevaluate, as long as the same operator expression continues to be called with the sameVarianttypes. If the types change, it will fall back toevaluate, which would be faster with this change. Thesum_intandsum_floatbenchmarks below are meant to show this case -sum_intusesints when calculating the sum insum_array, thensum_floatcallssum_arrayusingfloats.Compared with gdscript below:
old:
new: