Class: ABProf::ABWorker

Inherits:
Object
  • Object
show all
Defined in:
lib/abprof.rb

Overview

This class is used by programs that are being profiled. It’s necessarily a singleton since it needs to control STDIN. The bare mode can do without it, but it’s needed for harness processes.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.debug(string) ⇒ Object



32
33
34
# File 'lib/abprof.rb', line 32

def self.debug string
  STDERR.puts(string) if ABProf.debug
end

.iteration(&block) ⇒ Object



36
37
38
39
# File 'lib/abprof.rb', line 36

def self.iteration(&block)
  @iter_block = block
  @return = :none
end

.iteration_with_return_value(&block) ⇒ Object



41
42
43
44
# File 'lib/abprof.rb', line 41

def self.iteration_with_return_value(&block)
  @iter_block = block
  @return = :per_iteration
end

.n_interations_with_return_value(&block) ⇒ Object



46
47
48
49
# File 'lib/abprof.rb', line 46

def self.n_interations_with_return_value(&block)
  @iter_block = block
  @return = :per_n_iterations
end

.read_onceObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/abprof.rb', line 77

def self.read_once
  debug "WORKER #{Process.pid}: read loop"
  @input ||= ""
  @input += (STDIN.gets || "")
  debug "WORKER #{Process.pid}: Input #{@input.inspect}"
  if @input["\n"]
    command, @input = @input.split("\n", 2)
    debug "WORKER #{Process.pid}: command: #{command.inspect}"
    if command == "QUIT"
      exit 0
    elsif command["ITERS"]
      iters = command[5..-1].to_i
      values = run_n iters
      STDOUT.flush  # Why does this synchronous file descriptor not flush when given a string with a newline? Ugh!
      debug "WORKER #{Process.pid}: finished command ITERS: OK"
    else
      STDERR.puts "Unrecognized ABProf command: #{command.inspect}!"
      exit -1
    end
  end
end

.run_n(n) ⇒ Object



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
# File 'lib/abprof.rb', line 51

def self.run_n(n)
  debug "WORKER #{Process.pid}: running #{n} times"

  case @return
  when :none
    n.times do
      @iter_block.call
    end
    STDOUT.write "OK\n"
  when :per_iteration
    values = (0..(n-1)).map { |i| @iter_block.call.to_f }
    STDOUT.write "VALUES #{values.inspect}"
  when :per_n_iterations
    value = @iter_block.call(n)
    if value.respond_to?(:each)
      # Return array of numbers
      STDOUT.write "VALUES #{value.to_a.inspect}"
    else
      # Return single number
      STDOUT.write "VALUE #{value.to_f}"
    end
  else
    raise "Unknown @return value #{@return.inspect} inside abprof!"
  end
end

.startObject



99
100
101
102
103
# File 'lib/abprof.rb', line 99

def self.start
  loop do
    read_once
  end
end

Instance Method Details

#debug(string) ⇒ Object



29
30
31
# File 'lib/abprof.rb', line 29

def debug string
  STDERR.puts(string) if ABProf.debug
end