summaryrefslogtreecommitdiffstats
path: root/lib/puppet
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2009-04-21 17:49:05 -0500
committerJames Turnbull <james@lovedthanlost.net>2009-04-22 14:53:14 +1000
commit828b1ea605786183c69a8be3bca2272b50761790 (patch)
tree53a01136bef3d799fc4895d2cfbee5859f810c58 /lib/puppet
parent9f32172e7d93f926b2ab291e68bdd0cc955ff3d2 (diff)
downloadpuppet-828b1ea605786183c69a8be3bca2272b50761790.tar.gz
puppet-828b1ea605786183c69a8be3bca2272b50761790.tar.xz
puppet-828b1ea605786183c69a8be3bca2272b50761790.zip
Fixing #2182 - SimpleGraph#walk is now iterative
It was previously recursive, and was causing significant performance problems for large, wide graphs. Signed-off-by: Luke Kanies <luke@madstop.com>
Diffstat (limited to 'lib/puppet')
-rw-r--r--lib/puppet/simple_graph.rb19
1 files changed, 15 insertions, 4 deletions
diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb
index b1aaf6363..05420eab9 100644
--- a/lib/puppet/simple_graph.rb
+++ b/lib/puppet/simple_graph.rb
@@ -364,10 +364,21 @@ class Puppet::SimpleGraph
end
# Just walk the tree and pass each edge.
- def walk(source, direction, &block)
- adjacent(source, :direction => direction).each do |target|
- yield source, target
- walk(target, direction, &block)
+ def walk(source, direction)
+ # Use an iterative, breadth-first traversal of the graph. One could do
+ # this recursively, but Ruby's slow function calls and even slower
+ # recursion make the shorter, recursive algorithm cost-prohibitive.
+ stack = [source]
+ seen = Set.new
+ until stack.empty?
+ node = stack.shift
+ next if seen.member? node
+ connected = adjacent(node, :direction => direction)
+ connected.each do |target|
+ yield node, target
+ end
+ stack.concat(connected)
+ seen << node
end
end