lib/sfplanner/planner.rb in sfplanner-0.2.1 vs lib/sfplanner/planner.rb in sfplanner-0.2.3

- old
+ new

@@ -192,27 +192,39 @@ solutions = get_possible_plans(partial_inits) merged_plan = merge_plans(solutions) end def solve_classical_task(params={}) - @plan, @sas_task = self.solve_sas(@parser, params) + benchmarks = {} + benchmarks[:solve_sas] = Benchmark.measure { + @plan, @sas_task = self.solve_sas(@parser, params) + } return @plan if params[:sas_plan] return to_bsig(params) if params[:bsig] - plan = (params[:parallel] ? self.get_parallel_plan : self.get_sequential_plan) + plan = nil + benchmarks[:get_parallel_plan] = Benchmark.measure { + plan = (params[:parallel] ? self.get_parallel_plan : self.get_sequential_plan) + } - if params[:dot] - to_dot(plan) - elsif params[:json] - JSON.generate(plan) - elsif params[:pretty_json] - JSON.pretty_generate(plan) - else - plan - end + output = nil + + benchmarks[:to_json] = Benchmark.measure { + if params[:dot] + output = to_dot(plan) + elsif params[:json] + output = JSON.generate(plan) + elsif params[:pretty_json] + output = JSON.pretty_generate(plan) + else + output = plan + end + } + + output end def bsig_template return {'version' => 1, 'operators' => [], 'id' => Time.now.getutc.to_i, 'goal' => {}, 'goal_operator' => {}} end @@ -345,46 +357,65 @@ end def solve_sas(parser, p={}) return nil if parser.nil? - tmp_dir = '/tmp/nuri_' + (Time.now.to_f * 1000000).to_i.to_s + tmp_dir = "/tmp/nuri_#{(Time.now.to_f * 1000000).to_i}" begin - compile_time = Benchmark.measure do + benchmarks = {} + + benchmarks['compile step 1'] = Benchmark.measure do parser.compile_step_1 + end + + benchmarks['sas_post_processor'] = Benchmark.measure do p[:sas_post_processor].sas_post_processor(parser) if p[:sas_post_processor] + end + + benchmarks['compile step 2'] = Benchmark.measure do parser.compile_step_2 end while File.exist?(tmp_dir) - tmp_dir = '/tmp/nuri_' + (rand * 100000).to_i.abs.to_s + tmp_dir = "/tmp/nuri_#{(rand * 100000).to_i.abs}" end Dir.mkdir(tmp_dir) - benchmarks = parser.benchmarks - benchmarks['compile time'] = compile_time + benchmarks.merge!(parser.benchmarks) - sas_file = tmp_dir + '/problem.sas' - plan_file = tmp_dir + '/out.plan' + sas_file = "#{tmp_dir}/problem.sas" + plan_file = "#{tmp_dir}/out.plan" benchmarks['generating sas'] = Benchmark.measure do File.open(sas_file, 'w') do |f| - f.write(parser.sas) + f.write parser.sas f.flush end end benchmarks['search_time'] = Benchmark.measure do planner = ParallelHeuristic.new(tmp_dir, sas_file, plan_file) planner.solve end + File.open("#{tmp_dir}/#{TranslatorBenchmarkFile}", 'w') do |f| + data = {} + benchmarks.each do |label,bm| + data[label] = { + :user => (bm.utime + bm.cutime).round(3), + :sys => (bm.stime + bm.cstime).round(3), + :real => bm.real.round(3), + } + end + f.write(JSON.pretty_generate(data)) + end + plan = (File.exist?(plan_file) ? File.read(plan_file) : nil) - plan = plan_preprocessing(plan) + #plan = plan_preprocessing(plan) - if plan != nil + if not plan.nil? plan = extract_sas_plan(plan, parser) - sas_task = Nuri::Sas::Task.new(sas_file) + sas_task = Sfp::Sas::Task.new(sas_file) sas_task.sas_plan = plan tmp = [] goal_op = nil plan.each do |op| @@ -393,15 +424,14 @@ next if name == 'goal' or name == 'globalop' or name == 'sometime' tmp.push(op) end sas_task.goal_operator_name = goal_op plan = tmp + + return plan, sas_task end - File.open(tmp_dir + '/' + TranslatorBenchmarkFile, 'w') { |f| f.write(JSON.pretty_generate(benchmarks)) } - - return plan, sas_task rescue Exception => exp raise exp ensure File.delete('plan_numbers_and_cost') if File.exist?('plan_numbers_and_cost') Kernel.system('rm -rf ' + tmp_dir) if not @debug @@ -414,16 +444,15 @@ os = `uname -s`.downcase.strip machine = `uname -m`.downcase.strip planner = nil if os == 'linux' and machine[0,3] == 'x86' - planner = File.expand_path(File.dirname(__FILE__) + '/../../bin/solver/linux-x86') + planner = File.expand_path("#{File.dirname(__FILE__)}/../../bin/solver/linux-x86") elsif os == 'linux' and machine[0,3] == 'arm' - planner = File.expand_path(File.dirname(__FILE__) + '/../../bin/solver/linux-arm') - #Sfp::Planner::Config.set_max_memory(512) + planner = File.expand_path("#{File.dirname(__FILE__)}/../../bin/solver/linux-arm") elsif os == 'macos' or os == 'darwin' - planner = File.expand_path(File.dirname(__FILE__) + '/../../bin/solver/macos') + planner = File.expand_path("#{File.dirname(__FILE__)}/../../bin/solver/macos") end raise UnsupportedPlatformException, "#{os} is not supported" if planner.nil? planner end @@ -487,34 +516,27 @@ def self.getcommand(dir, sas_file, plan_file, heuristic='ff', debug=false, timeout=nil) planner = Sfp::Planner.path params = Sfp::Planner.parameters(heuristic) timeout = Sfp::Planner::Config.timeout if timeout.nil? - os = `uname -s`.downcase.strip - command = case os + case `uname -s `.downcase.strip when 'linux' - then "cd #{dir}; " + - "ulimit -Sv #{Sfp::Planner::Config.max_memory}; " + - "#{planner}/preprocess < #{sas_file} 2>/dev/null 1>/dev/null; " + - "if [ -f 'output' ]; then " + - "timeout #{timeout} nice #{planner}/downward #{params} " + - "--plan-file #{plan_file} < output 1>>search.log 2>>search.log; fi" + then "cd #{dir} && \ + ulimit -Sv #{Sfp::Planner::Config.max_memory} && \ + #{planner}/preprocess < #{sas_file} 2>/dev/null 1>/dev/null && \ + if [ -f 'output' ]; then \ + timeout #{timeout} nice #{planner}/downward #{params} \ + --plan-file #{plan_file} < output 1>>search.log 2>>search.log; fi" when 'macos', 'darwin' - then "cd #{dir}; " + - "ulimit -Sv #{Sfp::Planner::Config.max_memory}; " + - "#{planner}/preprocess < #{sas_file} 1>/dev/null 2>/dev/null ; " + - "if [ -f 'output' ]; then " + - "nice #{planner}/downward #{params} " + - "--plan-file #{plan_file} < output 1>>search.log 2>>search.log; fi" + then "cd #{dir} && \ + ulimit -Sv #{Sfp::Planner::Config.max_memory} && \ + #{planner}/preprocess < #{sas_file} 1>/dev/null 2>/dev/null && \ + if [ -f 'output' ]; then \ + nice #{planner}/downward #{params} \ + --plan-file #{plan_file} < output 1>>search.log 2>>search.log; fi" else nil end - - #if not command.nil? and (os == 'linux' or os == 'macos' or os == 'darwin') - # command = "#{command}" #1> /dev/null 2>/dev/null" - #end - - command end def self.get_search_command(dir, plan_file, heuristic, timeout=nil) planner = Sfp::Planner.path params = Sfp::Planner.parameters(heuristic) @@ -715,14 +737,27 @@ @optimize = optimize end @timeout = (ENV['SFPLANNER_TIMEOUT'] ? ENV['SFPLANNER_TIMEOUT'].to_i : Sfp::Planner::Config.timeout) end + def pids(dir='') + `ps ax | grep -v grep | grep downward | grep sfplanner | grep '#{dir}' | awk '{print $1" "}'`.to_s.strip.split("\n") + end + def solve + def kill(dir='') + system "kill -9 #{pids(dir).join(' ')} 1>/dev/null 2>/dev/null" + end + ### run preprocessing return false if not do_preprocess + ['HUP', 'KILL', 'INT'].each { |name,id| + dir = @dir + Signal.trap(name) { kill(dir) } + } + ### save current working dir home = Dir.pwd ### change to temporary working dir Dir.chdir @dir @@ -735,23 +770,19 @@ pid = Process.spawn cmd Process.detach pid files << plan_file end - def processes(dir) - `ps ax | grep -v grep | grep downward | grep sfplanner | grep '#{dir}' | awk '{print $1" "}'`.to_s.strip.split("\n") - end - loop do - list = processes(@dir) + list = pids(@dir) break if list.length <= 0 finished = files.select { |f| File.exist?(f) } break if finished.length > 0 sleep 0.2 end - system "kill -9 " + processes(@dir).join(" ") + " 1>/dev/null 2>/dev/null" + kill(@dir) ### select best plan selected = nil length = -1 files.each do |file| @@ -772,9 +803,12 @@ true else Dir.chdir home false end + + ensure + kill(@dir) end def do_preprocess (!!system(Sfp::Planner.get_preprocess_command(@dir, @sas_file)) && File.exist?(@dir + '/output'))