summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLamont Granquist <lamont@scriptkiddie.org>2017-10-17 11:07:15 -0700
committerLamont Granquist <lamont@scriptkiddie.org>2017-10-17 11:07:15 -0700
commitbfc892a2555acc89c1ae4d34e96a9cf99427ac33 (patch)
tree3ba6f9b784f19cc91e7f641b2a362559db9064c9
parent8132a92d854955ba6de12dd20289dfa9989313ab (diff)
downloadchef-lcg/turbo-merge.tar.gz
turboize arrayslcg/turbo-merge
Signed-off-by: Lamont Granquist <lamont@scriptkiddie.org>
-rw-r--r--lib/chef/node/immutable_collections.rb46
1 files changed, 36 insertions, 10 deletions
diff --git a/lib/chef/node/immutable_collections.rb b/lib/chef/node/immutable_collections.rb
index 3378bee2b5..4edaf586cd 100644
--- a/lib/chef/node/immutable_collections.rb
+++ b/lib/chef/node/immutable_collections.rb
@@ -132,6 +132,7 @@ class Chef
def reset
@generated_cache = false
+ @short_circuit_attr_level = nil
internal_clear # redundant?
end
@@ -141,13 +142,26 @@ class Chef
@generated_cache = true
end
+ # This can be set to e.g. [ :@default ] by the parent container to cause this container
+ # to only use the default level and to bypass deep merging (the common case is either
+ # default-level or automatic-level and we aren't doing any deep merging). Right now it
+ # "optimized" for the case where we're no longer merging anything and only tracking a
+ # single level, and setting this to anything other than a size=1 array would behave
+ # in a broken fashion. That could be fixed, but the perf boost would likely not be
+ # that large in the typical case.
+ #
+ # @api private
+ attr_accessor :short_circuit_attr_levels
+
private
+ # deep merging of array attribute within normal and override where they are merged together
def combined_components(components)
combined_values = nil
components.each do |component|
values = __node__.attributes.instance_variable_get(component).read(*__path__)
next unless values.is_a?(Array)
+ @tracked_components << component
combined_values ||= []
combined_values += values
end
@@ -157,6 +171,7 @@ class Chef
def get_array(component)
array = __node__.attributes.instance_variable_get(component).read(*__path__)
if array.is_a?(Array)
+ @tracked_components << component
array
end # else nil
end
@@ -164,14 +179,25 @@ class Chef
def generate_cache
internal_clear
components = []
- components << combined_components(Attribute::DEFAULT_COMPONENTS)
- components << get_array(:@normal)
- components << combined_components(Attribute::OVERRIDE_COMPONENTS)
- components << get_array(:@automatic)
+ @tracked_components = []
+ if short_circuit_attr_levels
+ components << get_array(short_circuit_attr_levels.first)
+ else
+ components << combined_components(Attribute::DEFAULT_COMPONENTS)
+ components << get_array(:@normal)
+ components << combined_components(Attribute::OVERRIDE_COMPONENTS)
+ components << get_array(:@automatic)
+ end
highest = components.compact.last
if highest.is_a?(Array)
internal_replace( highest.each_with_index.map { |x, i| convert_value(x, __path__ + [ i ] ) } )
end
+ if @tracked_components.size == 1
+ # tracked_components is accurate enough to tell us if we're not really merging
+ internal_each do |key, value|
+ value.short_circuit_attr_levels = @tracked_components if value.respond_to?(:short_circuit_attr_levels)
+ end
+ end
end
# needed for __path__
@@ -283,12 +309,12 @@ class Chef
def generate_cache
internal_clear
components = short_circuit_attr_levels ? short_circuit_attr_levels : Attribute::COMPONENTS.reverse
- # merged_components is not entirely accurate due to the short-circuit
- merged_components = []
+ # tracked_components is not entirely accurate due to the short-circuit
+ tracked_components = []
components.each do |component|
subhash = __node__.attributes.instance_variable_get(component).read(*__path__)
unless subhash.nil? # FIXME: nil is used for not present
- merged_components << component
+ tracked_components << component
if subhash.kind_of?(Hash)
subhash.keys.each do |key|
next if internal_key?(key)
@@ -299,10 +325,10 @@ class Chef
end
end
end
- if merged_components.size == 1
- # merged_components is accurate enough to tell us if we're not really merging
+ if tracked_components.size == 1
+ # tracked_components is accurate enough to tell us if we're not really merging
internal_each do |key, value|
- value.short_circuit_attr_levels = merged_components if value.respond_to?(:short_circuit_attr_levels)
+ value.short_circuit_attr_levels = tracked_components if value.respond_to?(:short_circuit_attr_levels)
end
end
end