class Roby::App::Debug

A command library that allows to control StackProf to profile a Roby application

Public Instance Methods

default_path(prefix) click to toggle source

@api private

The filename that is used by default in {#save}. It is relative to {#path}

It is a time tag (down to the milliseconds) followed by the sampling mode and a .dump extension

# File lib/roby/app/debug.rb, line 88
def default_path(prefix)
    path = File.join(app.log_dir, 'debug')
    time = Time.now.strftime("%Y-%m-%d.%H%M%S.%3N")
    File.join(path, "#{prefix}-#{time}.dump")
end
memdump(path: default_path('memdump'), run_gc: true) click to toggle source

Perform a memory dump

# File lib/roby/app/debug.rb, line 110
def memdump(path: default_path('memdump'), run_gc: true)
    FileUtils.mkdir_p File.dirname(path)
    File.open(path, 'wb') do |io|
        GC.start(full_mark: true, immediate_sweep: true) if run_gc
        ObjectSpace.dump_all(output: io)
    end
    path
end
stackprof_active?() click to toggle source
# File lib/roby/app/debug.rb, line 64
def stackprof_active?
    !!@cycle_counter_handler
end
stackprof_save(path: default_path('stackprof-%s')) click to toggle source

Save the current profiling results into the path given to {#start}

@param [String]

# File lib/roby/app/debug.rb, line 97
def stackprof_save(path: default_path('stackprof-%s'))
    if results = StackProf.results
        path = path % [results[:mode]]
        FileUtils.mkdir_p(File.dirname(path))
        File.open(path, 'wb') do |f|
            f.write Marshal.dump(results)
        end
        path
    end
end
stackprof_start(one_shot: false, cycles: nil, mode: :cpu, interval: nil, raw: false) click to toggle source

Start profiling

@param [Boolean] one_shot automatically stop and save after cycles

cycles, or one cycle if cycles is nil

@param [Integer] cycles a number of cycles after which the

profiling is stopped and saved

@param [String] path the path into which results should be saved @param [Symbol] mode one of :cpu, :wall or :object @param [Integer] interval the sampling interval in microseconds

for :cpu and :wall (defaults to 1000, that is 1ms), and the
sampling rate in objects allocated for :object (defaults to 1)

@param [Boolean] raw whether the dump should include raw samples,

needed e.g. for flamegraph generation
# File lib/roby/app/debug.rb, line 23
def stackprof_start(one_shot: false, cycles: nil, mode: :cpu, interval: nil, raw: false)
    interval ||= if mode == :object then 1
                 else 1000
                 end
    StackProf.start(mode: mode, interval: interval, raw: raw)

    if one_shot && !cycles
        cycles = 1
    end

    if cycles
        remaining_cycles = cycles
        @cycle_counter_handler = execution_engine.at_cycle_begin do
            remaining_cycles -= 1
            if remaining_cycles == 0
                execution_engine.at_cycle_end(once: true) do
                    remaining_cycles = cycles
                    StackProf.stop
                    path = stackprof_save
                    app.notify "profiling", 'INFO', "results saved in #{path} after #{cycles} cycles"
                    if one_shot
                        app.notify "profiling", 'INFO', "stopped"
                        execution_engine.remove_propagation_handler(@cycle_counter_handler)
                        @cycle_counter_handler = nil
                    else
                        StackProf.start(mode: mode, interval: interval)
                    end
                end
            end
        end
        nil
    end
end
stackprof_stop() click to toggle source

Stop profiling

This does not save the results, call {#save} for this

# File lib/roby/app/debug.rb, line 72
def stackprof_stop
    StackProf.stop
    if @cycle_counter_handler
        execution_engine.remove_propagation_handler(@cycle_counter_handler)
        @cycle_counter_handler = nil
    end
end
trace_allocations(enable) click to toggle source

Enable or disable allocation traces for {#memdump}

# File lib/roby/app/debug.rb, line 122
def trace_allocations(enable)
    if enable
        ObjectSpace.trace_object_allocations_start
    else
        ObjectSpace.trace_object_allocations_stop
        ObjectSpace.trace_object_allocations_clear
    end
end