[Pkg-puppet-devel] [SCM] Puppet packaging for Debian branch, experimental, updated. debian/2.6.8-1-844-g7ec39d5

Daniel Pittman daniel at rimspace.net
Tue May 10 08:04:25 UTC 2011


The following commit has been merged in the experimental branch:
commit 2cf45283d7eea90461f1c9606af710bf5645076a
Author: Daniel Pittman <daniel at rimspace.net>
Date:   Mon Jan 24 22:23:41 2011 -0800

    Feature #2597 -- eliminate OpenStruct for performance...
    
    A bit of profiling shows that most of the time spent in clustering is spent
    trolling around through OpenStruct.  Replacing this with a hash or, where
    sane, an array for the stack frame in our non-recursive implementations makes
    performance significantly faster.  (3 seconds to .65 seconds faster.)
    
    I guess those developer niceties do have some cost after all.  Better to take
    the hit on readability and prefer performance here.

diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb
index 5833cf7..1b5ffdc 100644
--- a/lib/puppet/simple_graph.rb
+++ b/lib/puppet/simple_graph.rb
@@ -1,7 +1,6 @@
 require 'puppet/external/dot'
 require 'puppet/relationship'
 require 'set'
-require 'ostruct'
 
 # A hopefully-faster graph class to replace the use of GRATR.
 class Puppet::SimpleGraph
@@ -100,41 +99,41 @@ class Puppet::SimpleGraph
   def tarjan(root, s)
     # initialize the recursion stack we use to work around the nasty lack of a
     # decent Ruby stack.
-    recur = [OpenStruct.new :node => root]
+    recur = [{ :node => root }]
 
     while not recur.empty? do
       frame = recur.last
-      vertex = frame.node
+      vertex = frame[:node]
 
-      case frame.step
+      case frame[:step]
       when nil then
-        s.index[vertex]   = s.number
-        s.lowlink[vertex] = s.number
-        s.number          = s.number + 1
+        s[:index][vertex]   = s[:number]
+        s[:lowlink][vertex] = s[:number]
+        s[:number]          = s[:number] + 1
 
-        s.stack.push(vertex)
-        s.seen[vertex] = true
+        s[:stack].push(vertex)
+        s[:seen][vertex] = true
 
-        frame.children = adjacent(vertex)
-        frame.step     = :children
+        frame[:children] = adjacent(vertex)
+        frame[:step]     = :children
 
       when :children then
-        if frame.children.length > 0 then
-          child = frame.children.shift
-          if ! s.index[child] then
+        if frame[:children].length > 0 then
+          child = frame[:children].shift
+          if ! s[:index][child] then
             # Never seen, need to recurse.
-            frame.step = :after_recursion
-            frame.child = child
-            recur.push OpenStruct.new :node => child
-          elsif s.seen[child] then
-            s.lowlink[vertex] = [s.lowlink[vertex], s.index[child]].min
+            frame[:step] = :after_recursion
+            frame[:child] = child
+            recur.push({ :node => child })
+          elsif s[:seen][child] then
+            s[:lowlink][vertex] = [s[:lowlink][vertex], s[:index][child]].min
           end
         else
-          if s.lowlink[vertex] == s.index[vertex] then
+          if s[:lowlink][vertex] == s[:index][vertex] then
             this_scc = []
             begin
-              top = s.stack.pop
-              s.seen[top] = false
+              top = s[:stack].pop
+              s[:seen][top] = false
               this_scc << top
             end until top == vertex
             # NOTE: if we don't reverse we get the components in the opposite
@@ -148,17 +147,17 @@ class Puppet::SimpleGraph
             # better with a reverse operation than a string of 'unshift'
             # insertions at the head of the array; if they were going to mess
             # up the performance of one, it would be unshift.
-            s.scc << this_scc.reverse
+            s[:scc] << this_scc.reverse
           end
           recur.pop               # done with this node, finally.
         end
 
       when :after_recursion then
-        s.lowlink[vertex] = [s.lowlink[vertex], s.lowlink[frame.child]].min
-        frame.step = :children
+        s[:lowlink][vertex] = [s[:lowlink][vertex], s[:lowlink][frame[:child]]].min
+        frame[:step] = :children
 
       else
-        fail "#{frame.step} is an unknown step"
+        fail "#{frame[:step]} is an unknown step"
       end
     end
   end
@@ -170,18 +169,19 @@ class Puppet::SimpleGraph
   # This has an unhealthy relationship with the 'tarjan' method above, which
   # it uses to implement the detection of strongly connected components.
   def find_cycles_in_graph
-    state = OpenStruct.new :number => 0, :index => {}, :lowlink => {}, :scc => [],
-                           :stack => [], :seen => {}
+    state = {
+      :number => 0, :index => {}, :lowlink => {}, :scc => [],
+      :stack => [], :seen => {}
+    }
 
     # we usually have a disconnected graph, must walk all possible roots
     vertices.each do |vertex|
-      if ! state.index[vertex] then
+      if ! state[:index][vertex] then
         tarjan vertex, state
       end
     end
 
-    result = state.scc.select { |c| c.length > 1 }
-    return result
+    state[:scc].select { |c| c.length > 1 }
   end
 
   # Perform a BFS on the sub graph representing the cycle, with a view to
@@ -202,18 +202,15 @@ class Puppet::SimpleGraph
 
     found = []
 
-    stack = [OpenStruct.new :vertex => cycle.first, :path => []]
+    # frame struct is vertex, [path]
+    stack = [[cycle.first, []]]
     while frame = stack.shift do
-      if frame.path.member? frame.vertex then
-        found << frame.path + [frame.vertex]
-
-        # REVISIT: This should be an O(1) test, but I have no idea if Ruby
-        # specifies Array#length to be O(1), O(n), or allows the implementer
-        # to pick either option.  Should answer that. --daniel 2011-01-23
+      if frame[1].member?(frame[0]) then
+        found << frame[1] + [frame[0]]
         break if found.length >= max_paths
       else
-        adj[frame.vertex].each do |to|
-          stack.push OpenStruct.new :vertex => to, :path => frame.path + [frame.vertex]
+        adj[frame[0]].each do |to|
+          stack.push [to, frame[1] + [frame[0]]]
         end
       end
     end

-- 
Puppet packaging for Debian



More information about the Pkg-puppet-devel mailing list