Fix O(n) check making accessing many elements O(n**2) #54
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Primed by seeing @jrafanie's O(N**2) fix #52,
I was byebug-ing through my code into
new_ostruct_member
and noticed another O(n**2):I say small n because it's number of direct subelements not whole tree size.
However I'm a bit shocked that it makes even tiny 1-element ROS 2.5 times faster(!) — probably because
.methods
includes 85 inherited methods even before new_ostruct_member adds any.(note
methods(false)
below being fast for small hash but still O(n**2) for large hash).This is perhaps why #52 did not see such a big improvement...
Microbenchmark (using same data @jrafanie used, large hash has 579 keys, ends up with 1737 methods):
https://github.com/cben/recursive-open-struct/blob/benchmark-methods-include/benchmark.rb
Essentially creates ROS from a hash, then 5 times doing
.foo
read access on all fields.This includes several ways I've tried to do this check, some buggy approximations.
I'm not sure this check it's needed at all (
false
is without) — AFAICTnew_ostruct_member
is only called frommethod_missing
so can assume we don't have the method yet — butmethod_defined?
is negligibly cheap.I have some more ideas (though not enough time) for RecursiveOpenStruct and/or OpenStruct performance. Are there any benchmarks you use? cc @sferik
method_missing
every time! For my microbenchmark, not creating methods is 1.5~2 faster than any of the above:env HERESY=1 SHARE=1 ruby benchmark.rb
=> https://benchmark.fyi/y, https://benchmark.fyi/z, https://benchmark.fyi/A