diff --git a/examples/graph.dot b/examples/graph.dot index b524cd25..36453a5f 100644 --- a/examples/graph.dot +++ b/examples/graph.dot @@ -1,96 +1,106 @@ digraph "Profile" { -label="WALL_TIME >=0%\nTotal: 1.401074" +label="WALL_TIME >=0%\nTotal: 1.382985"; +labelloc=t; +labeljust=l; subgraph "Thread 2148237740" { -2159428720 [label="run_primes\n(100%)"]; -2159428720 -> 2159429580 [label="2/2"]; -2159428720 -> 2159428880 [label="2/2"]; -2159428800 [label="[]=\n(0%)"]; -2159428880 [label="make_random_array\n(1%)"]; -2159428880 -> 2159429420 [label="2/2"]; -2159428880 -> 2159429040 [label="2/2"]; -2159428960 [label="%\n(15%)"]; -2159429040 [label="new\n(0%)"]; -2159429040 -> 2159429340 [label="2/2"]; -2159429040 -> 2159429820 [label="2/2"]; -2159429120 [label="rand\n(0%)"]; -2159429200 [label="-\n(0%)"]; -2159429260 [label="setup\n(100%)"]; -2159429260 -> 2159430040 [label="1/1"]; -2159429260 -> 2159428720 [label="1/2"]; -2159429340 [label="initialize\n(0%)"]; -2159429420 [label="each_index\n(1%)"]; -2159429420 -> 2159429120 [label="20000/20000"]; -2159429420 -> 2159428800 [label="20000/20000"]; -2159429500 [label="is_prime\n(98%)"]; -2159429500 -> 2159429740 [label="20000/20000"]; -2159429500 -> 2159429200 [label="20000/20000"]; -2159429580 [label="find_primes\n(99%)"]; -2159429580 -> 2159429660 [label="2/2"]; -2159429660 [label="select\n(99%)"]; -2159429660 -> 2159429500 [label="20000/20000"]; -2159429740 [label="upto\n(97%)"]; -2159429740 -> 2159428960 [label="1593581/1593581"]; -2159429740 -> 2159429920 [label="1593581/1593581"]; -2159429820 [label="allocate\n(0%)"]; -2159429920 [label="==\n(12%)"]; -2159430040 [label="go\n(50%)"]; -2159430040 -> 2159428720 [label="1/2"]; +2159427600 [label="[]=\n(0%)"]; +2159427680 [label="%\n(15%)"]; +2159427760 [label="run_primes\n(100%)"]; +2159427760 -> 2159428600 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159427760 -> 2159428300 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159427840 [label="new\n(0%)"]; +2159427840 -> 2159428080 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159427840 -> 2159428760 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159427920 [label="rand\n(0%)"]; +2159428000 [label="-\n(0%)"]; +2159428080 [label="initialize\n(0%)"]; +2159428160 [label="each_index\n(1%)"]; +2159428160 -> 2159427920 [label="20000/20000" fontsize=10 fontcolor="#666666"]; +2159428160 -> 2159427600 [label="20000/20000" fontsize=10 fontcolor="#666666"]; +2159428220 [label="go\n(49%)"]; +2159428220 -> 2159427760 [label="1/2" fontsize=10 fontcolor="#666666"]; +2159428300 [label="make_random_array\n(1%)"]; +2159428300 -> 2159428160 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159428300 -> 2159427840 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159428360 [label="setup\n(100%)"]; +2159428360 -> 2159427760 [label="1/2" fontsize=10 fontcolor="#666666"]; +2159428360 -> 2159428220 [label="1/1" fontsize=10 fontcolor="#666666"]; +2159428440 [label="select\n(99%)"]; +2159428440 -> 2159428520 [label="20000/20000" fontsize=10 fontcolor="#666666"]; +2159428520 [label="is_prime\n(98%)"]; +2159428520 -> 2159428680 [label="20000/20000" fontsize=10 fontcolor="#666666"]; +2159428520 -> 2159428000 [label="20000/20000" fontsize=10 fontcolor="#666666"]; +2159428600 [label="find_primes\n(99%)"]; +2159428600 -> 2159428440 [label="2/2" fontsize=10 fontcolor="#666666"]; +2159428680 [label="upto\n(97%)"]; +2159428680 -> 2159427680 [label="1562487/1562487" fontsize=10 fontcolor="#666666"]; +2159428680 -> 2159428920 [label="1562487/1562487" fontsize=10 fontcolor="#666666"]; +2159428760 [label="allocate\n(0%)"]; +2159428920 [label="==\n(12%)"]; } -subgraph cluster_2159104080 { +subgraph cluster_2159103200 { label = "Object"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429580; -2159429500; -2159428880; -2159428720; +2159428600; +2159428520; +2159428300; +2159427760; } -subgraph cluster_2159104200 { +subgraph cluster_2159103260 { label = "Integer"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429740; +2159428680; } -subgraph cluster_2159104380 { +subgraph cluster_2159103060 { label = "PrintersTest"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159430040; -2159429260; +2159428360; +2159428220; } -subgraph cluster_2159104140 { +subgraph cluster_2159103120 { label = "Array"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429660; -2159429420; -2159429340; -2159428800; +2159428440; +2159428160; +2159428080; +2159427600; } -subgraph cluster_2159104280 { +subgraph cluster_2159103340 { label = ""; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429820; +2159428760; } -subgraph cluster_2159103860 { +subgraph cluster_2159102840 { label = "Class"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429040; +2159427840; } -subgraph cluster_2159104000 { +subgraph cluster_2159102980 { label = "Kernel"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429120; +2159427920; } -subgraph cluster_2159104340 { +subgraph cluster_2159103400 { label = "Fixnum"; fontcolor = "#666666"; +fontsize = 16; color = "#666666"; -2159429920; -2159429200; -2159428960; +2159428920; +2159428000; +2159427680; } } diff --git a/examples/graph.png b/examples/graph.png new file mode 100644 index 00000000..33ed5761 Binary files /dev/null and b/examples/graph.png differ diff --git a/lib/ruby-prof/dot_printer.rb b/lib/ruby-prof/dot_printer.rb index 30029a49..359b946f 100644 --- a/lib/ruby-prof/dot_printer.rb +++ b/lib/ruby-prof/dot_printer.rb @@ -2,7 +2,7 @@ require 'ruby-prof/abstract_printer' module RubyProf - # Generates graphviz graph in dot format. + # Generates a graphviz graph in dot format. # To use the dot printer: # # result = RubyProf.profile do @@ -19,6 +19,8 @@ module RubyProf # class DotPrinter < RubyProf::AbstractPrinter CLASS_COLOR = '"#666666"' + EDGE_COLOR = '"#666666"' + # Creates the DotPrinter using a RubyProf::Result. def initialize(result) super(result) @@ -27,7 +29,7 @@ def initialize(result) # Print a graph report to the provided output. # - # output - Any IO oject, including STDOUT or a file. The default value is + # output - Any IO object, including STDOUT or a file. The default value is # STDOUT. # # options - Hash of print options. See #setup_options @@ -41,17 +43,26 @@ def initialize(result) def print(output = STDOUT, options = {}) @output = output setup_options(options) - mode = RubyProf.constants.find{|c| RubyProf.const_get(c) == RubyProf.measure_mode} + total_time = thread_times.values.inject{|a,b| a+b} puts 'digraph "Profile" {' - puts "label=\"#{mode} >=#{min_percent}%\\nTotal: #{total_time}\"" + puts "label=\"#{mode_name} >=#{min_percent}%\\nTotal: #{total_time}\";" + puts "labelloc=t;" + puts "labeljust=l;" print_threads puts '}' end private + # Something of a hack, figure out which constant went with the + # RubyProf.measure_mode so that we can display it. Otherwise it's easy to + # forget what measurement was made. + def mode_name + mode = RubyProf.constants.find{|c| RubyProf.const_get(c) == RubyProf.measure_mode} + end + # Computes the total time per thread: def thread_times @thread_times ||= begin @@ -97,7 +108,7 @@ def print_methods(thread_id, methods) name = method_name(method).split("#").last puts "#{dot_id(method)} [label=\"#{name}\\n(#{total_percentage.round}%)\"];" @seen_methods << method - print_children(total_time, method) + print_edges(total_time, method) end end @@ -110,6 +121,7 @@ def print_classes(thread_id, methods) puts "subgraph cluster_#{cls.object_id} {" puts "label = \"#{cls}\";" puts "fontcolor = #{CLASS_COLOR};" + puts "fontsize = 16;" puts "color = #{CLASS_COLOR};" big_methods.each do |m| puts "#{m.object_id};" @@ -119,14 +131,14 @@ def print_classes(thread_id, methods) end end - def print_children(total_time, method) + def print_edges(total_time, method) method.aggregate_children.sort_by(&:total_time).reverse.each do |child| target_percentage = (child.target.total_time / total_time) * 100.0 next if target_percentage < min_percent # Get children method - puts "#{dot_id(method)} -> #{dot_id(child.target)} [label=\"#{child.called}/#{child.target.called}\"];" + puts "#{dot_id(method)} -> #{dot_id(child.target)} [label=\"#{child.called}/#{child.target.called}\" fontsize=10 fontcolor=#{EDGE_COLOR}];" end end