Class: ABProf::ABHarnessProcess

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(command_line, opts = {}) ⇒ ABHarnessProcess

Returns a new instance of ABHarnessProcess.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/abprof.rb', line 188

def initialize command_line, opts = {}
  debug "Controller of nobody yet: SPAWN"
  @in_reader, @in_writer = IO.pipe
  @out_reader, @out_writer = IO.pipe
  @in_writer.sync = true
  @out_writer.sync = true

  @pid = fork do
    STDOUT.reopen(@out_writer)
    STDIN.reopen(@in_reader)
    @out_reader.close
    @in_writer.close
    if command_line.respond_to?(:call)
      puts "Caution! An ABProf Harness process (non-bare) is being used with a block. This is almost never what you want!"
      command_line.call
    elsif command_line.respond_to?(:to_s)
      exec command_line.to_s
    else
      raise "Don't know how to execute benchmark code: #{command_line.inspect}!"
    end
    exit! 0
  end
  @out_writer.close
  @in_reader.close

  @debug = opts[:debug]
  debug "Controller spawned #{@pid} (debug: #{@debug.inspect})"
end

Instance Attribute Details

#last_itersObject (readonly)

Returns the value of attribute last_iters.



182
183
184
# File 'lib/abprof.rb', line 182

def last_iters
  @last_iters
end

#last_runObject (readonly)

Returns the value of attribute last_run.



181
182
183
# File 'lib/abprof.rb', line 181

def last_run
  @last_run
end

Instance Method Details

#debug(string) ⇒ Object



184
185
186
# File 'lib/abprof.rb', line 184

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

#killObject



222
223
224
225
226
# File 'lib/abprof.rb', line 222

def kill
  debug "Controller of #{@pid}: DIE"
  ::Process.detach @pid
  ::Process.kill "TERM", @pid
end

#quitObject



217
218
219
220
# File 'lib/abprof.rb', line 217

def quit
  debug "Controller of #{@pid}: QUIT"
  @in_writer.write "QUIT\n"
end

#run_iters(n) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/abprof.rb', line 228

def run_iters(n)
  debug "Controller of #{@pid}: #{n} ITERS"
  @in_writer.write "ITERS #{n.to_i}\n"

  ignored_out = 0
  state = :failed
  t_start = Time.now
  loop do
    # Read and block
    output = @out_reader.gets
    ignored_out += output.length
    puts "Controller of #{@pid} out: #{output.inspect}" if @debug
    debug "Controller of #{@pid} out: #{output.inspect}"
    if output =~ /^VALUES/ # These anchors match newlines, too
      state = :succeeded
      vals = MultiJson.load output[7..-1]
      raise "Must return an array value from iterations!" unless vals.is_a?(Array)
      raise "Must return an array of numbers from iterations!" unless vals[0].is_a?(Numeric)
      @last_run = vals
    elsif output =~ /^VALUE/ # These anchors match newlines, too
      state = :succeeded
      val = output[6..-1].to_f
      raise "Must return a number from iterations!" unless val.is_a?(Numeric)
      @last_run = [ val ]
    elsif output =~ /^OK$/   # These anchors match newlines, too
      state = :succeeded_get_time
      break
    end
    if output =~ /^NOT OK$/ # These anchors match newlines, too
      # Failed, break
      state = :explicit_not_ok
      break
    end
    if ignored_out > 10_000
      # 10k of output and no OK? Bail with failed state.
      state = :too_much_output_without_status
      break
    end
  end
  t_end = Time.now
  unless [:succeeded, :succeeded_get_time].include?(state)
    self.kill
    STDERR.puts "Killing process #{@pid} after failed iterations, error code #{state.inspect}"
  end

  @last_run = [ (t_end - t_start).to_f ] if state == :succeeded_get_time
  @last_iters = n

  @last_run
end