Class: Arachni::Support::Profiler

Inherits:
Object
  • Object
show all
Defined in:
lib/arachni/support/profiler.rb

Overview

Author:

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.write_samples_to_disk(file, options = {}) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/arachni/support/profiler.rb', line 19

def self.write_samples_to_disk( file, options = {} )
    profiler = Support::Profiler.new

    Thread.new do
        begin
            loop do
                profiler.write_object_space( file, options )
                sleep options[:interval] || 1
            end
        rescue => e
            ap e
            ap e.backtrace
        end
    end
end

Instance Method Details

#count_objects(klass) ⇒ Object



130
131
132
# File 'lib/arachni/support/profiler.rb', line 130

def count_objects( klass )
    ObjectSpace.each_object( klass ){}
end

#find_dependencies(_object_id, _mapped = {}) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/arachni/support/profiler.rb', line 56

def find_dependencies( _object_id, _mapped = {} )
    mapped = _mapped
    points_to_object = find_references( Mass[_object_id] )
    ids = points_to_object.keys.map { |x| /\#(\d*)/.match(x).captures.first.to_i }
    mapped[_object_id] = points_to_object#ids

    unmapped = ids - mapped.keys
    unmapped.each do |x|
        new_deps = find_dependencies( x, mapped )
        mapped.merge( new_deps )
    end
    mapped
end

#find_references(o) ⇒ Object



52
53
54
# File 'lib/arachni/support/profiler.rb', line 52

def find_references( o )
    Mass.references( o )
end

#object_space(options = {}) ⇒ Object



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
# File 'lib/arachni/support/profiler.rb', line 80

def object_space( options = {} )
    klass       = options[:class]
    namespaces  = options[:namespaces] || [Arachni]
    max_entries = options[:max_entries] || 50

    object_space    = Hash.new(0)
    @object_space ||= Hash.new(0)

    ObjectSpace.each_object do |o|
        next if o.class != klass && !object_within_namespace?( o, namespaces )
        object_space[o.class] += 1
    end

    object_space = Hash[object_space.sort_by { |_, v| v }.reverse[0..max_entries]]

    with_deltas = object_space.dup
    with_deltas.each do |k, v|
        if v.is_a? Numeric
            with_deltas[k] = "#{v} (#{v - @object_space[k].to_i})"
        else
            with_deltas[k] = v
        end
    end

    @object_space = object_space.dup
    with_deltas
end


70
71
72
73
# File 'lib/arachni/support/profiler.rb', line 70

def print_dependencies( o )
    ap 'Dependencies'
    ap find_dependencies( o.object_id )
end


40
41
42
43
44
45
46
47
48
49
50
# File 'lib/arachni/support/profiler.rb', line 40

def print_object_allocations( o )
    ap 'Object ID:   ' + o.object_id.to_s
    ap 'Source file: ' + ObjectSpace.allocation_sourcefile(o)
    ap 'Source line: ' + ObjectSpace.allocation_sourceline(o).to_s
    ap 'Generation:  ' + ObjectSpace.allocation_generation(o).to_s
    ap 'Class path:  ' + ObjectSpace.allocation_class_path(o).to_s
    ap 'Method:      ' + ObjectSpace.allocation_method_id(o).to_s
    ap 'Memsize:     ' + ObjectSpace.memsize_of(o).to_s
    #ap 'Reachable:   ' + ObjectSpace.reachable_objects_from(o).to_s  #=> [referenced, objects, ...]
    ap '-' * 200
end


126
127
128
# File 'lib/arachni/support/profiler.rb', line 126

def print_object_space( options = {} )
    ap object_space( options )
end


75
76
77
78
# File 'lib/arachni/support/profiler.rb', line 75

def print_references( o )
    ap 'References'
    ap find_references( o )
end

#resource_consumptionObject



134
135
136
137
138
139
140
141
# File 'lib/arachni/support/profiler.rb', line 134

def resource_consumption
    procinfo = ::Sys::ProcTable.ps( Process.pid )
    {
        cpu_utilization:    procinfo[:pctcpu],
        memory_utilization: procinfo[:pctmem],
        memory_usage:       rss_to_mb( procinfo[:rss] )
    }
end

#rss_to_mb(rss) ⇒ Object



143
144
145
# File 'lib/arachni/support/profiler.rb', line 143

def rss_to_mb( rss )
    rss * 4096.0 / 1024.0 / 1024.0
end

#trace_allocationsObject



35
36
37
38
# File 'lib/arachni/support/profiler.rb', line 35

def trace_allocations
    require 'objspace'
    ObjectSpace.trace_object_allocations_start
end

#write_object_space(file, options = {}) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/arachni/support/profiler.rb', line 108

def write_object_space( file, options = {} )
    consumption = resource_consumption

    str = "RAM: #{consumption[:memory_usage].round(3)}MB"
    str << " (#{consumption[:memory_utilization]}%)"
    str << " - CPU: #{consumption[:cpu_utilization]}%\n\n"

    os      = object_space( options )
    maxsize = os.keys.map(&:to_s).map(&:size).sort.reverse.first

    os.each do |klass, info|
        offset = maxsize - klass.to_s.size
        str << "#{klass}: #{' ' * offset}#{info}\n"
    end

    IO.write( file, str )
end