-
Notifications
You must be signed in to change notification settings - Fork 898
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ancestry Patches #17360
Ancestry Patches #17360
Conversation
Looking into the test failures on this one. Unsure what the issue is. |
Failure is due to the memoization of Thank god for the tests around that though... |
df6cc28
to
0e6173d
Compare
Prevents a new version of the STRING_BASED_KEYS array from being instantiated every time that cast_primary_key is called. * * * Before/After ------------ Total allocated: 324542397 bytes (3095350 objects) | Total allocated: 318431331 bytes (2943673 objects) | allocated objects by gem | allocated objects by gem ----------------------------------- | ----------------------------------- 1576834 activerecord-5.0.7 | 1576834 activerecord-5.0.7 477120 manageiq/app | 477120 manageiq/app 418737 ancestry-2.2.2 <<<<<<<<<< | 274449 activemodel-5.0.7 274449 activemodel-5.0.7 | 267060 ancestry-2.2.2 <<<<<<<<<< 106559 activesupport-5.0.7 | 106559 activesupport-5.0.7 82799 pending | 82799 pending 74117 ruby-2.3.3/lib | 74117 ruby-2.3.3/lib ... | ...
Calls `.map!` instead of `.map` since we already have a temp array from the `.split`, and this avoids creating a completely new array for the second time in this method. * * * Before/After ------------ Total allocated: 318431331 bytes (2943673 objects) | Total allocated: 316196585 bytes (2917071 objects) | allocated objects by gem | allocated objects by gem ----------------------------------- | ----------------------------------- 1576834 activerecord-5.0.7 | 1576834 activerecord-5.0.7 477120 manageiq/app | 477120 manageiq/app 274449 activemodel-5.0.7 | 274449 activemodel-5.0.7 267060 ancestry-2.2.2 <<<<<<<<<< | 208479 manageiq/lib 106559 activesupport-5.0.7 | 106557 activesupport-5.0.7 82799 pending | 82799 pending 74117 ruby-2.3.3/lib | 74117 ruby-2.3.3/lib 52875 manageiq-providers-vmware-0be2f13a0dc9 | 52875 manageiq-providers-vmware-0be2f13a0dc9 14424 fast_gettext-1.2.0 | 35578 ancestry-2.2.2 <<<<<<<<<< ... | ...
In many methods, this is generated twice because the result is never saved. This simply adds memoization to the result of this method. Of Note: The extra `#clear_memoized_instance_variables` additions were necessary to fix failing tests due to ancestry records being updated and saved, and the `@_ancestor_ids` value became out of date. * * * Before/After ------------ **Note:** Only the totals here change... which is a bit weird and I didn't notice it before (probably just a reporting error on MemoryProfiler's end), but this patch was the only thing changed between the two runs. Total allocated: 316196585 bytes (2917071 objects) | Total allocated: 307262021 bytes (2762757 objects) ^^^^^^^ | ^^^^^^^ | allocated objects by gem | allocated objects by gem ----------------------------------- | ----------------------------------- 1576834 activerecord-5.0.7 | 1559102 activerecord-5.0.7 477120 manageiq/app | 477120 manageiq/app 274449 activemodel-5.0.7 | 274449 activemodel-5.0.7 208479 manageiq/lib | 106559 activesupport-5.0.7 106557 activesupport-5.0.7 | 82799 pending 82799 pending | 74117 ruby-2.3.3/lib 74117 ruby-2.3.3/lib | 71895 manageiq/lib 52875 manageiq-providers-vmware-0be2f13a0dc9 | 52875 manageiq-providers-vmware-0be2f13a0dc9 35578 ancestry-2.2.2 <<<<<<<<<< | 35578 ancestry-2.2.2 <<<<<<<< ... | ...
Makes '/' a constant so it isn't allocated every time `parse_ancestry_column` is called. A minor improvement here, but will help with future commits.
51fcab2
to
b7e3d2d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just found that one thing.
Thanks for helping get ancestry better
lib/patches/ancestry_patch.rb
Outdated
def parent_id | ||
return @_parent_id if defined?(@_parent_id) | ||
@_parent_id = if @ancestor_ids | ||
@ancestor_ids.empty? ? nil : @ancestor_ids.last |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a) think we need @_ancestor_ids
with the underscore
Are we expecting to only call parent_id
and not use any other ancestor_ids methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh butts... you are totally right. Good catch.
Wonder if that affected my metrics at all. 🤔
col = read_attribute(ancestry_base_class.ancestry_column) | ||
# Specifically not using `.blank?` here because it is | ||
# slower than doing the below. | ||
if col.nil? || col.empty? # rubocop:disable Rails/Blank |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I like col&.empty?
- will remove the rails/blank comments and is faster
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so tell me. How do you really feel about &.
?
end | ||
|
||
STRING_BASED_KEYS = %i[string uuid text].freeze | ||
def cast_primary_key(key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious if the new casting changes are good enough to make this not necessary anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
curious if the new casting changes are good enough to make this not necessary anymore
Possible. There are definitely things that are now obsolete in this patch that are fixed upstream.
That said, these are meant to be the minimal viable changes that can be shipped with MIQ with the current version of ancestry that we are using. My guess is that for backporting, we can't/shouldn't upgrade the version of ancestry we are using.
Not saying we shouldn't upgrade ancestry
in master, but I see it as not feasible/safe to take what has been done in the gem and just merge it in for a backport. This patch is intended for fine
/gaprindashvili
.
If @ancestor_ids has already been calculated, using that value will be much more efficient for calculating the depth since the work to do so has already been done. But if it hasn't (for example, when calling `.arrange_nodes`), then ancestor_ids is never actually needed in full, and we can avoid the object allocations and CPU cycles needed to determine the depth and simply count the number of instances of '/' in the string using `String#count` (doesn't allocate any objects in doing so). `@_depth`, like `@_ancestor_ids`, needs to be reset if the tree is changed.
If @ancestor_ids has already been calculated, using that value will be much more efficient for calculating the parent since the work translate the string to the proper typecasted value has already been done. But if it hasn't (for example, when calling `.arrange_nodes`), then ancestor_ids is never actually needed in full, and we can avoid the object allocations and CPU cycles needed to determine the depth by typecasting all of the ids in the string and just use a bit of substring manipulation to only allocate one object prior to typecasting (instead of N+1 for number of ancestors). Also, since it is possible for `@_parent_id` to be `nil`, make sure we are removing the instance variable instead of just setting it to `nil` if the location in the tree has been changed.
b7e3d2d
to
c0b8b69
Compare
Checked commits NickLaMuro/manageiq@4f361f2~...c0b8b69 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 lib/patches/ancestry_patch.rb
|
@miq-bot add_label fine/yes, gaprindashvili/yes |
^ I see the above labels as possibly debatable. I can work with whoever is needed on deciding what we want to and not want to backport from this PR. |
FYI this broke-ish (it broke tests for dead code) UI master :)
Fixed in ManageIQ/manageiq-ui-classic#4011 @simaishi please backport this with that UI PR ☝️ Thanks :) @NickLaMuro For Gaprindashvili it's ok but for Fine adding new Tenant will be broken because it will not be saved with correct |
@ZitaNemeckova Thanks! I will look into that then, and also update the description regarding your fix for |
If it helps this line is the problem. Edit: Fixed the link. Thanks Nick. |
@NickLaMuro Tracked down failing tests in https://github.com/ManageIQ/manageiq-automation_engine#manageiq-automation-engine to this PR. Tests started failing here: https://travis-ci.org/ManageIQ/manageiq-automation_engine/jobs/385973677 Any help would be appreciated. |
Sorry about that... taking a look now. |
Correction to @ZitaNemeckova 's link, I believe that this line is what is what was causing the issue (made it a permalink instead of pointing to master). |
So wanted to give an update because this is failing in more than one place now... 😞 So the issue in both cases is due to the memoization be held on for the variables after something in the tree structure has changed. I put in a piece of code to handle this: https://github.com/ManageIQ/manageiq/blob/a49e48a4/lib/patches/ancestry_patch.rb#L1-L11 But it looks like it is isn't getting fired correctly in the specs when things change. Possibly due to the fact that the records we are working with haven't been saved to the DB, and there are specs that work against With module AncestryInstanceMethodsPatch
def update_descendants_with_new_ancestry
# ...
end
def parent=(parent)
super
update_descendants_with_new_ancestry
end
def parent_id=(parent_id)
super
update_descendants_with_new_ancestry
end
end Which will clear out the instance variable Removing all of the memoization fixes everything just fine, but I am trying to avoid doing that if I can help it. I will update later when I think I have a better fix in place for both, or have more to share. |
Figured it out! Patch to fix incoming. |
Here is the patch: This patch should remove the need to backport ManageIQ/manageiq-ui-classic#4011 along with this PR to |
Tests are passing locally for me with this change in place. Thanks @NickLaMuro. 👍 |
Ancestry Patches (cherry picked from commit 095f4dc) https://bugzilla.redhat.com/show_bug.cgi?id=1593798
Fine backport details:
|
Ancestry Patches (cherry picked from commit 095f4dc) https://bugzilla.redhat.com/show_bug.cgi?id=1593797
Gaprindashvili backport details:
|
Various patches to ancestry to help with performance of
miq_request_workflow.rb
. Will eventually work them into the main project, but for now, this is the best way to introduce the changes without needing to bump the version of ancestry in the process.Benchmarks
The benchmark script used here basically runs the following:
And is targeting a fairly large EMS, with about 600 hosts.
Note: The benchmarks for this change do NOT include the changes from other PRs (#17354 for example). Benchmarks of all changes can be found here.
Links