File: graph_printer.rb

package info (click to toggle)
ruby-prof 0.16.2%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,680 kB
  • ctags: 972
  • sloc: ruby: 4,552; ansic: 1,888; makefile: 6
file content (116 lines) | stat: -rw-r--r-- 4,126 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# encoding: utf-8

module RubyProf
  # Generates graph[link:files/examples/graph_txt.html] profile reports as text.
  # To use the graph printer:
  #
  #   result = RubyProf.profile do
  #     [code to profile]
  #   end
  #
  #   printer = RubyProf::GraphPrinter.new(result)
  #   printer.print(STDOUT, {})
  #
  # The constructor takes two arguments. See the README

  class GraphPrinter < AbstractPrinter
    PERCENTAGE_WIDTH = 8
    TIME_WIDTH = 11
    CALL_WIDTH = 17

    private

    def print_header(thread)
      @output << "Measure Mode: %s\n" % RubyProf.measure_mode_string
      @output << "Thread ID: #{thread.id}\n"
      @output << "Fiber ID: #{thread.fiber_id}\n" unless thread.id == thread.fiber_id
      @output << "Total Time: #{thread.total_time}\n"
      @output << "Sort by: #{sort_method}\n"
      @output << "\n"

      # 1 is for % sign
      @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
      @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
      @output << sprintf("%#{TIME_WIDTH}s", "total")
      @output << sprintf("%#{TIME_WIDTH}s", "self")
      @output << sprintf("%#{TIME_WIDTH}s", "wait")
      @output << sprintf("%#{TIME_WIDTH}s", "child")
      @output << sprintf("%#{CALL_WIDTH}s", "calls")
      @output << "     name"
      @output << "\n"
    end

    def print_methods(thread)
      total_time = thread.total_time
      # Sort methods from longest to shortest total time
      methods = thread.methods.sort_by(&sort_method)

      # Print each method in total time order
      methods.reverse_each do |method|
        total_percentage = (method.total_time/total_time) * 100
        next if total_percentage < min_percent

        self_percentage = (method.self_time/total_time) * 100

        @output << "-" * 80 << "\n"
        print_parents(thread, method)

        # 1 is for % sign
        @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage)
        @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage)
        @output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", method.children_time)
        @output << sprintf("%#{CALL_WIDTH}i", method.called)
        @output << sprintf("    %s",  method.recursive? ? "*" : " ")
        @output << sprintf("%s", method_name(method))
        if print_file
          @output << sprintf("  %s:%s", method.source_file, method.line)
        end
        @output << "\n"

        print_children(method)
      end
    end

    def print_parents(thread, method)
      method.aggregate_parents.sort_by(&:total_time).each do |caller|
        next unless caller.parent
        @output << " " * 2 * PERCENTAGE_WIDTH
        @output << sprintf("%#{TIME_WIDTH}.3f", caller.total_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", caller.self_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", caller.wait_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", caller.children_time)

        call_called = "#{caller.called}/#{method.called}"
        @output << sprintf("%#{CALL_WIDTH}s", call_called)
        @output << sprintf("     %s", caller.parent.target.full_name)
        @output << "\n"
      end
    end

    def print_children(method)
      method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
        # Get children method

        @output << " " * 2 * PERCENTAGE_WIDTH

        @output << sprintf("%#{TIME_WIDTH}.3f", child.total_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", child.self_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", child.wait_time)
        @output << sprintf("%#{TIME_WIDTH}.3f", child.children_time)

        call_called = "#{child.called}/#{child.target.called}"
        @output << sprintf("%#{CALL_WIDTH}s", call_called)
        @output << sprintf("     %s", child.target.full_name)
        @output << "\n"
      end
    end

    def print_footer(thread)
      @output << "\n"
      @output << "* indicates recursively called methods\n"
    end
  end
end