On Oct 22, 2009, at 11:13 AM, Brice Figureau wrote:
>
> Hi,
>
> Please disregard the previous version of this patch which was plain
> wrong.
> Mainly due to the fact that I thought ":include" was a synonim of
> ":joins"
> in Active Record parlance.
> This one is now correct and should generate the correct query.
>
> Marc: can you try this one and report success/failure?
>
> Please review and comment,
>
> Thanks,
> Brice
>
> Original Commit Msg:
>
> f9516d introduced a change in the way the user tags are persisted
> to the database: user tags are now treated as regular tags (they are
> stored to the tags table).
> Thus this commit changed the AR collector request to also look at the
> tags tables when collecting.
>
> Unfortunately this added a performance regression since tag request
> were still importing the resources parameters tables and AR was
> issuing a large request which was returning all the resource
> parameters
> joined with the tags.
>
> This commit fixes the AR request to join to the needed table, instead
> of doing an include. Including (ie eager loading) parameter values was
> not working for resource parameters anyway since at least 0.24 because
> searching by parameter add a constraint to the joins and only the
> searched parameter was returned instead of all parameter for a given
> exported resource. So on a performance standpoint this new code should
> be as fast 0.24 was.
>
> Signed-off-by: Brice Figureau <[email protected]>
> ---
> lib/puppet/parser/collector.rb | 22 ++++++++++++++--------
> spec/unit/parser/collector.rb | 29 ++++++++++++++++++++---------
> 2 files changed, 34 insertions(+), 17 deletions(-)
>
> diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/
> collector.rb
> index a7f81b4..a6763c4 100644
> --- a/lib/puppet/parser/collector.rb
> +++ b/lib/puppet/parser/collector.rb
> @@ -102,18 +102,24 @@ class Puppet::Parser::Collector
> raise Puppet::DevError, "Cannot collect resources for a nil
> host" unless @scope.host
> host = Puppet::Rails::Host.find_by_name(@scope.host)
>
> - query = {:include => {:param_values => :param_name}}
> -
> search = "(exported=? AND restype=?)"
> values = [true, @type]
>
> search += " AND (%s)" % @equery if @equery
>
> - # this is a small performance optimisation
> - # the tag mechanism involves 3 more joins, which are
> - # needed only if we query on tags.
> - if search =~ /puppet_tags/
> - query[:include][:puppet_tags] = :resource_tags
> + # note:
> + # we're not eagerly including any relations here because
> + # it can creates so much objects we'll throw out later.
> + # We used to eagerly include param_names/values but the way
> + # the search filter is built ruined those efforts and we
> + # were eagerly loading only the searched parameter and not
> + # the other ones.
> + query = {}
> + case search
> + when /puppet_tags/
> + query = {:joins => {:resource_tags => :puppet_tag}}
> + when /param_name/
> + query = {:joins => {:param_values => :param_name}}
> end
>
> # We're going to collect objects from rails, but we don't
> want any
> @@ -139,7 +145,7 @@ class Puppet::Parser::Collector
> # and such, we'll need to vary the conditions, but this
> works with no
> # attributes, anyway.
> time = Puppet::Util.thinmark do
> - Puppet::Rails::Resource.find(:all, @type, true,
> query).each do |obj|
> + Puppet::Rails::Resource.find(:all, query).each do |obj|
What happened to the use of @type and 'exported' to reduce the number
of resources returned? Won't this return all resources, regardless of
whether they're exported or the right type?
> if resource = exported_resource(obj)
> count += 1
> resources << resource
> diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/
> collector.rb
> index 926033c..7f88bf7 100755
> --- a/spec/unit/parser/collector.rb
> +++ b/spec/unit/parser/collector.rb
> @@ -498,35 +498,46 @@ describe Puppet::Parser::Collector, "when
> building its ActiveRecord query for co
>
> Puppet
> ::Rails::Host.expects(:find_by_name).with(@scope.host).returns(@host)
>
> Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> - options = arguments[3]
> + options = arguments[1]
> options[:conditions][0] =~ /^host_id != \?/ and
> options[:conditions][1] == 5
> }.returns([...@resource])
>
> @collector.evaluate.should == [...@resource]
> end
>
> - it "should return parameter names, parameter values when
> querying ActiveRecord" do
> + it "should join with parameter names, parameter values when
> querying ActiveRecord" do
> + @collector.equery = "param_names.name = title"
> Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> - options = arguments[3]
> - options[:include] == {:param_values => :param_name}
> + options = arguments[1]
> + options[:joins] == {:param_values => :param_name}
> }.returns([...@resource])
>
> @collector.evaluate.should == [...@resource]
> end
>
> - it "should return tags when querying ActiveRecord with a tag
> exported query" do
> + it "should join with tag tables when querying ActiveRecord with
> a tag exported query" do
> @collector.equery = "puppet_tags.name = test"
> Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> - options = arguments[3]
> - options[:include] == {:param_values
> => :param_name, :puppet_tags => :resource_tags}
> + options = arguments[1]
> + options[:joins] == {:resource_tags => :puppet_tag}
> }.returns([...@resource])
>
> @collector.evaluate.should == [...@resource]
> end
>
> + it "should not join parameters when querying ActiveRecord with
> a tag exported query" do
> + @collector.equery = "puppet_tags.name = test"
> + Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> + options = arguments[1]
> + options[:joins] == {:param_values => :param_name}
> + }.returns([...@resource])
> +
> + @collector.evaluate.should be_false
> + end
> +
> it "should only search for exported resources with the matching
> type" do
> Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> - options = arguments[3]
> + options = arguments[1]
> options[:conditions][0].include?("(exported=? AND
> restype=?)") and options[:conditions][1] == true and
> options[:conditions][2] == "Mytype"
> }.returns([...@resource])
>
> @@ -536,7 +547,7 @@ describe Puppet::Parser::Collector, "when
> building its ActiveRecord query for co
> it "should include the export query if one is provided" do
> @collector.equery = "test = true"
> Puppet::Rails::Resource.stubs(:find).with { |*arguments|
> - options = arguments[3]
> + options = arguments[1]
> options[:conditions][0].include?("test = true")
> }.returns([...@resource])
>
> --
> 1.6.4
>
>
> >
--
It is better to sleep on things beforehand than lie awake about them
afterward. -- Baltasar Gracian
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://madstop.com
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---