jkr 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +81 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +674 -0
- data/{README.txt → README.rdoc} +0 -0
- data/Rakefile +4 -5
- data/bin/console +7 -0
- data/etc/example.plan +32 -0
- data/etc/zsh-comp.sh +82 -0
- data/exe/jkr +6 -0
- data/jkr.gemspec +31 -0
- data/lib/jkr.rb +13 -4
- data/lib/jkr/analysis.rb +5 -14
- data/lib/jkr/analytics.rb +75 -0
- data/lib/jkr/array.rb +47 -0
- data/lib/jkr/blktrace.rb +131 -0
- data/lib/jkr/cli.rb +110 -0
- data/lib/jkr/cpu_usage.rb +81 -0
- data/lib/jkr/cpufreq.rb +201 -0
- data/lib/jkr/dirlock.rb +9 -0
- data/lib/jkr/env.rb +17 -17
- data/lib/jkr/error.rb +5 -0
- data/lib/jkr/numeric.rb +28 -0
- data/lib/jkr/plan.rb +317 -26
- data/lib/jkr/planfinder.rb +40 -0
- data/lib/jkr/plot.rb +626 -0
- data/lib/jkr/stat.rb +2 -0
- data/lib/jkr/stat/kmeans-1d.rb +94 -0
- data/lib/jkr/su_cmd +163 -0
- data/lib/jkr/sysinfo.rb +34 -0
- data/lib/jkr/trial.rb +91 -16
- data/lib/jkr/userutils.rb +300 -22
- data/lib/jkr/utils.rb +38 -314
- data/lib/jkr/version.rb +3 -0
- data/sample-jkr.plan +52 -0
- metadata +171 -63
- data/bin/jkr +0 -224
- data/test/test_jkr.rb +0 -8
    
        data/lib/jkr/cli.rb
    ADDED
    
    | @@ -0,0 +1,110 @@ | |
| 1 | 
            +
            require 'thor'
         | 
| 2 | 
            +
            require 'term/ansicolor'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Jkr
         | 
| 5 | 
            +
              class CLI < ::Thor
         | 
| 6 | 
            +
                include Term::ANSIColor
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                class_option :debug, :type => :boolean
         | 
| 9 | 
            +
                class_option :directory, :type => :string, :default => Dir.pwd, :aliases => :C
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def self.exit_on_failure?
         | 
| 12 | 
            +
                  true
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                desc "init", "Initialize a Jkr environment"
         | 
| 16 | 
            +
                def init()
         | 
| 17 | 
            +
                  dir = options[:directory]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  jkr_dir    = File.join(dir, "jkr")
         | 
| 20 | 
            +
                  result_dir = File.join(dir, "jkr", "result")
         | 
| 21 | 
            +
                  plan_dir   = File.join(dir, "jkr", "plan")
         | 
| 22 | 
            +
                  script_dir = File.join(dir, "jkr", "script")
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  puts "Preparing a new Jkr environment ... @ #{dir}"
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  [jkr_dir, result_dir, plan_dir, script_dir].each do |dir|
         | 
| 27 | 
            +
                    puts "  making directory: #{dir}"
         | 
| 28 | 
            +
                    FileUtils.mkdir(dir)
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  [result_dir, plan_dir, script_dir].each do |dir|
         | 
| 32 | 
            +
                    File.open(File.expand_path(".gitdir", dir), "w") do |_|
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  puts "  preparing an example plan: example.plan"
         | 
| 37 | 
            +
                  FileUtils.cp(File.expand_path("../../etc/example.plan", __dir__),
         | 
| 38 | 
            +
                               File.join(plan_dir, "example.plan"))
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  puts ""
         | 
| 41 | 
            +
                  puts "... done"
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                desc "list", "List executable plans"
         | 
| 45 | 
            +
                def list()
         | 
| 46 | 
            +
                  begin
         | 
| 47 | 
            +
                    @jkr_env = Jkr::Env.new(options[:directory])
         | 
| 48 | 
            +
                  rescue Errno::ENOENT
         | 
| 49 | 
            +
                    puts(red("[ERROR] jkr dir not found at #{@options[:directory]}"))
         | 
| 50 | 
            +
                    puts(red("        Maybe you are in a wrong directory."))
         | 
| 51 | 
            +
                    exit(false)
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  plans = Dir.glob("#{@jkr_env.jkr_plan_dir}/*.plan").map do |plan_file_path|
         | 
| 55 | 
            +
                    plan = Jkr::Plan.create_by_name(@jkr_env, File.basename(plan_file_path, ".plan"))
         | 
| 56 | 
            +
                    [File.basename(plan_file_path, ".plan"), plan.title]
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  if ENV["JKR_ZSHCOMP_HELPER"]
         | 
| 60 | 
            +
                    plans.each do |plan_name, plan_title|
         | 
| 61 | 
            +
                      puts "#{plan_name}[#{plan_title}]"
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                    return
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  puts "Existing plans:"
         | 
| 67 | 
            +
                  puts
         | 
| 68 | 
            +
                  maxlen = plans.map{|plan| plan[0].size}.max
         | 
| 69 | 
            +
                  plans.each do |plan|
         | 
| 70 | 
            +
                    printf(" %#{maxlen}s : %s\n", plan[0], plan[1])
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                  puts
         | 
| 73 | 
            +
                end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                desc "execute <plan> [<plan> ...]", "Execute plans"
         | 
| 76 | 
            +
                def execute(*plan_names)
         | 
| 77 | 
            +
                  @jkr_env = Jkr::Env.new(options[:directory])
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  if options[:debug]
         | 
| 80 | 
            +
                    delete_files_on_error = false
         | 
| 81 | 
            +
                  else
         | 
| 82 | 
            +
                    delete_files_on_error = true
         | 
| 83 | 
            +
                  end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                  if plan_names.size > 0
         | 
| 86 | 
            +
                    plan_name = plan_names.first
         | 
| 87 | 
            +
                    plan = Jkr::Plan.create_by_name(@jkr_env, plan_name)
         | 
| 88 | 
            +
                    Jkr::Trial.run(@jkr_env, plan, delete_files_on_error)
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                desc "analyze <result> [<result> ...]", "Run analysis script for executed results"
         | 
| 93 | 
            +
                def analyze(*result_ids)
         | 
| 94 | 
            +
                  @jkr_env = Jkr::Env.new(options[:directory])
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  result_ids.each do |arg|
         | 
| 97 | 
            +
                    Jkr::Analysis.analyze(@jkr_env, arg)
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                no_commands do
         | 
| 102 | 
            +
                  def find_plan_file(plan_name)
         | 
| 103 | 
            +
                    @jkr_env.plans.find do |plan_file_path|
         | 
| 104 | 
            +
                      File.basename(plan_file_path) == plan_name + ".plan"
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
            end # Jkr
         | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
             | 
| 2 | 
            +
            module Jkr
         | 
| 3 | 
            +
              class CpuUsageMonitor
         | 
| 4 | 
            +
                def initialize
         | 
| 5 | 
            +
                  @checkpoint1 = nil
         | 
| 6 | 
            +
                  @checkpoint2 = nil
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  self.checkpoint
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def read_stat
         | 
| 12 | 
            +
                  stat_str = `cat /proc/stat`
         | 
| 13 | 
            +
                  cpu_total = nil
         | 
| 14 | 
            +
                  cpus = Array.new
         | 
| 15 | 
            +
                  stat_str.each_line do |line|
         | 
| 16 | 
            +
                    case line
         | 
| 17 | 
            +
                    when /cpu (.*)$/
         | 
| 18 | 
            +
                      user, nice, sys, idle, *rest = $~[1].strip.split.map(&:to_i)
         | 
| 19 | 
            +
                      rest = rest.inject(&:+)
         | 
| 20 | 
            +
                      cpu_total = {:user => user, :sys => sys, :nice => nice, :idle => idle, :rest => rest}
         | 
| 21 | 
            +
                    when /cpu(\d+) (.*)$/
         | 
| 22 | 
            +
                      idx = $~[1].to_i
         | 
| 23 | 
            +
                      user, nice, sys, idle, *rest = $~[2].strip.split.map(&:to_i)
         | 
| 24 | 
            +
                      cpus[idx] = {:user => user, :sys => sys, :nice => nice, :idle => idle, :rest => rest}
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  {:system => cpu_total,
         | 
| 29 | 
            +
                    :cpus => cpus}
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def checkpoint
         | 
| 33 | 
            +
                  @checkpoint2 = @checkpoint1
         | 
| 34 | 
            +
                  @checkpoint1 = self.read_stat
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def reset
         | 
| 38 | 
            +
                  @checkpoint2 = @checkpoint1 = nil
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def checkpoint_and_get_usage
         | 
| 42 | 
            +
                  self.checkpoint
         | 
| 43 | 
            +
                  self.get_last_usage
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def get_usage
         | 
| 47 | 
            +
                  unless @checkpoint1
         | 
| 48 | 
            +
                    raise RuntimeError.new("Checkpointing is required")
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  self.calc_usage(self.read_stat[:system], @checkpoint1[:system])
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                def get_last_usage
         | 
| 55 | 
            +
                  unless @checkpoint1 && @checkpoint2
         | 
| 56 | 
            +
                    raise RuntimeError.new("At least two checkpoints are required")
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  self.calc_usage(@checkpoint2[:system], @checkpoint1[:system])
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def calc_usage(stat1, stat2)
         | 
| 63 | 
            +
                  stat1_clk, stat2_clk = [stat1, stat2].map{|stat|
         | 
| 64 | 
            +
                    stat.values.inject(&:+)
         | 
| 65 | 
            +
                  }
         | 
| 66 | 
            +
                  if stat1_clk > stat2_clk
         | 
| 67 | 
            +
                    stat1, stat2, stat1_clk, stat2_clk = [stat2, stat1, stat2_clk, stat1_clk]
         | 
| 68 | 
            +
                  elsif stat1_clk == stat2_clk
         | 
| 69 | 
            +
                    raise RuntimeError.new("Same clock count. cannot calc usage.")
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                  clk_diff = (stat2_clk - stat1_clk).to_f
         | 
| 72 | 
            +
                  ret = Hash.new
         | 
| 73 | 
            +
                  [:user, :sys, :nice, :idle].map{|key|
         | 
| 74 | 
            +
                    ret[key] = (stat2[key] - stat1[key]) / clk_diff
         | 
| 75 | 
            +
                  }
         | 
| 76 | 
            +
                  ret[:total] = 1.0 - ret[:idle]
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  ret
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
    
        data/lib/jkr/cpufreq.rb
    ADDED
    
    | @@ -0,0 +1,201 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'jkr/array'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Jkr
         | 
| 6 | 
            +
              class Cpufreq
         | 
| 7 | 
            +
                def self.cpupath(cpu_idx = nil)
         | 
| 8 | 
            +
                  if cpu_idx
         | 
| 9 | 
            +
                    self.cpupath() + "/cpu#{cpu_idx}"
         | 
| 10 | 
            +
                  else
         | 
| 11 | 
            +
                    "/sys/devices/system/cpu"
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def self.cpufreqpath(cpu_idx = 0)
         | 
| 16 | 
            +
                  cpupath(cpu_idx) + "/cpufreq"
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def self.num_cpu()
         | 
| 20 | 
            +
                  Dir.glob(cpupath("*")).select{|file| file =~ /cpu\d+$/}.size
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
                def self.available?()
         | 
| 24 | 
            +
                  (0..(self.num_cpu() - 1)).to_a.every?{|cpu_idx|
         | 
| 25 | 
            +
                    File.exists?(cpufreqpath(cpu_idx))
         | 
| 26 | 
            +
                  }
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def self.config()
         | 
| 30 | 
            +
                  Config.get()
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def self.available_frequency(cpu_idx = 0)
         | 
| 34 | 
            +
                  if self.available?
         | 
| 35 | 
            +
                    `cat #{cpufreqpath(cpu_idx) + "/scaling_available_frequencies"}`.strip.split.map(&:to_i).sort
         | 
| 36 | 
            +
                  else
         | 
| 37 | 
            +
                    []
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                class Config
         | 
| 42 | 
            +
                  attr_reader :cpuconfigs
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def initialize(*args)
         | 
| 45 | 
            +
                    @cpuconfigs = \
         | 
| 46 | 
            +
                    if args.size == 0
         | 
| 47 | 
            +
                      self.current_config
         | 
| 48 | 
            +
                    elsif args.size == 1 && args.first.is_a?(Hash)
         | 
| 49 | 
            +
                      arg = args.first
         | 
| 50 | 
            +
                      if ! arg[:governor]
         | 
| 51 | 
            +
                        raise ArgumentError.new("governor must be specified.")
         | 
| 52 | 
            +
                      elsif arg[:governor] == "userspace" && ! arg[:frequency]
         | 
| 53 | 
            +
                        raise ArgumentError.new("parameter :frequency is required for userspece governor")
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                      Array.new(Cpufreq.num_cpu()){|idx|
         | 
| 57 | 
            +
                        CpuConfig.new(idx, arg[:governor], arg)
         | 
| 58 | 
            +
                      }
         | 
| 59 | 
            +
                    elsif args.size == 1 && args.first.is_a?(Array) && args.first.every?{|arg| arg.is_a? CpuConfig}
         | 
| 60 | 
            +
                      args.first
         | 
| 61 | 
            +
                    elsif args.size == Cpufreq.num_cpu() && args.every?{|arg| arg.is_a? CpuConfig}
         | 
| 62 | 
            +
                      args
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                  def self.get()
         | 
| 67 | 
            +
                    cpuconfigs = Array.new(Cpufreq.num_cpu){|cpu_idx|
         | 
| 68 | 
            +
                      CpuConfig.read_config(cpu_idx)
         | 
| 69 | 
            +
                    }
         | 
| 70 | 
            +
                    self.new(cpuconfigs)
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  def self.set(config)
         | 
| 74 | 
            +
                    config.cpuconfigs.each_with_index{|cpuconfig, idx|
         | 
| 75 | 
            +
                      CpuConfig.write_config(idx, cpuconfig)
         | 
| 76 | 
            +
                    }
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  def to_s
         | 
| 80 | 
            +
                    cpuconfig = @cpuconfigs.first
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    ret = cpuconfig.governor
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    suffix = case cpuconfig.governor
         | 
| 85 | 
            +
                             when /\Aperformance\Z/
         | 
| 86 | 
            +
                               nil
         | 
| 87 | 
            +
                             when /\Apowersave\Z/
         | 
| 88 | 
            +
                               nil
         | 
| 89 | 
            +
                             when /\Auserspace\Z/
         | 
| 90 | 
            +
                               cpuconfig.params[:frequency] / 1000000.0
         | 
| 91 | 
            +
                             when /\Aondemand\Z/
         | 
| 92 | 
            +
                               nil
         | 
| 93 | 
            +
                             end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                    if suffix
         | 
| 96 | 
            +
                      ret += ":freq=#{suffix}GHz"
         | 
| 97 | 
            +
                    end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                    ret
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  class CpuConfig
         | 
| 103 | 
            +
                    attr_accessor :governor
         | 
| 104 | 
            +
                    attr_accessor :params
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                    # cpu_idx is just a hint for gathering information
         | 
| 107 | 
            +
                    def initialize(cpu_idx, gov, params = Hash.new)
         | 
| 108 | 
            +
                      @governor = gov.to_s
         | 
| 109 | 
            +
                      @freq = nil
         | 
| 110 | 
            +
                      @params = params
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                      @cpu_idx = cpu_idx
         | 
| 113 | 
            +
                      @available_freqs = Cpufreq.available_frequency(cpu_idx)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                      case @governor
         | 
| 116 | 
            +
                      when /\Aperformance\Z/
         | 
| 117 | 
            +
                        # do nothing
         | 
| 118 | 
            +
                      when /\Apowersave\Z/
         | 
| 119 | 
            +
                        # do nothing
         | 
| 120 | 
            +
                      when /\Auserspace\Z/
         | 
| 121 | 
            +
                        if ! @freq = params[:frequency]
         | 
| 122 | 
            +
                          raise ArgumentError.new("parameter :frequency is required for userspece governor")
         | 
| 123 | 
            +
                        elsif ! @available_freqs.include?(params[:frequency])
         | 
| 124 | 
            +
                          raise ArgumentError.new("Frequency not available: #{params[:frequency]}")
         | 
| 125 | 
            +
                        end
         | 
| 126 | 
            +
                      when /\Aondemand\Z/
         | 
| 127 | 
            +
                        # TODO
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    def frequency
         | 
| 132 | 
            +
                      case @governor
         | 
| 133 | 
            +
                      when /\Aperformance\Z/
         | 
| 134 | 
            +
                        @available_freqs.max
         | 
| 135 | 
            +
                      when /\Apowersave\Z/
         | 
| 136 | 
            +
                        @available_freqs.min
         | 
| 137 | 
            +
                      when /\Auserspace\Z/
         | 
| 138 | 
            +
                        @freq
         | 
| 139 | 
            +
                      when /\Aondemand\Z/
         | 
| 140 | 
            +
                        `cat #{Cpufreq.cpufreqpath(@cpu_idx) + "/scaling_cur_freq"}`.strip.to_i
         | 
| 141 | 
            +
                      end
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    def frequency=(freq)
         | 
| 145 | 
            +
                      if @available_freqs.include?(freq)
         | 
| 146 | 
            +
                        @freq = freq
         | 
| 147 | 
            +
                      else
         | 
| 148 | 
            +
                        raise ArgumentError.new("Frequency not available: #{freq}")
         | 
| 149 | 
            +
                      end
         | 
| 150 | 
            +
                    end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                    def self.read_config(cpu_idx)
         | 
| 153 | 
            +
                      gov = `cat #{Cpufreq.cpufreqpath(cpu_idx) + "/scaling_governor"}`.strip
         | 
| 154 | 
            +
                      freq = nil
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                      case gov
         | 
| 157 | 
            +
                      when /\Aperformance\Z/
         | 
| 158 | 
            +
                        # do nothing
         | 
| 159 | 
            +
                      when /\Aperformance\Z/
         | 
| 160 | 
            +
                        # do nothing
         | 
| 161 | 
            +
                      when /\Auserspace\Z/
         | 
| 162 | 
            +
                        freq = `cat #{Cpufreq.cpufreqpath(cpu_idx) + "/scaling_cur_freq"}`.strip.to_i
         | 
| 163 | 
            +
                      when /\Aondemand\Z/
         | 
| 164 | 
            +
                        # TODO: read parameters
         | 
| 165 | 
            +
                      end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                      CpuConfig.new(cpu_idx, gov, {:frequency => freq})
         | 
| 168 | 
            +
                    end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                    def self.write_config(cpu_idx, cpuconfig)
         | 
| 171 | 
            +
                      `echo #{cpuconfig.governor} > #{Cpufreq.cpufreqpath(cpu_idx) + "/scaling_governor"}`
         | 
| 172 | 
            +
                      case cpuconfig.governor
         | 
| 173 | 
            +
                      when /\Aperformance\Z/
         | 
| 174 | 
            +
                        # do nothing
         | 
| 175 | 
            +
                      when /\Aperformance\Z/
         | 
| 176 | 
            +
                        # do nothing
         | 
| 177 | 
            +
                      when /\Auserspace\Z/
         | 
| 178 | 
            +
                        `echo #{cpuconfig.frequency} > #{Cpufreq.cpufreqpath(cpu_idx) + "/scaling_setspeed"}`
         | 
| 179 | 
            +
                      when /\Aondemand\Z/
         | 
| 180 | 
            +
                        if cpuconfig.params[:up_threshold]
         | 
| 181 | 
            +
                          `echo #{cpuconfig.params[:up_threshold]} > #{Cpufreq.cpufreqpath(cpu_idx) + "/ondemand/up_threshold"}`
         | 
| 182 | 
            +
                        end
         | 
| 183 | 
            +
                        if cpuconfig.params[:sampling_rate]
         | 
| 184 | 
            +
                          `echo #{cpuconfig.params[:sampling_rate]} > #{Cpufreq.cpufreqpath(cpu_idx) + "/ondemand/sampling_rate"}`
         | 
| 185 | 
            +
                        end
         | 
| 186 | 
            +
                        # TODO: parameters
         | 
| 187 | 
            +
                      end
         | 
| 188 | 
            +
                    end
         | 
| 189 | 
            +
             | 
| 190 | 
            +
                    def to_s
         | 
| 191 | 
            +
                      case self.governor
         | 
| 192 | 
            +
                      when /\Auserspace\Z/
         | 
| 193 | 
            +
                        "#<CpuConfig: governor=#{self.governor}, frequency=#{self.frequency}>"
         | 
| 194 | 
            +
                      else
         | 
| 195 | 
            +
                        "#<CpuConfig: governor=#{self.governor}>"
         | 
| 196 | 
            +
                      end
         | 
| 197 | 
            +
                    end
         | 
| 198 | 
            +
                  end
         | 
| 199 | 
            +
                end
         | 
| 200 | 
            +
              end
         | 
| 201 | 
            +
            end
         | 
    
        data/lib/jkr/dirlock.rb
    ADDED
    
    
    
        data/lib/jkr/env.rb
    CHANGED
    
    | @@ -1,38 +1,38 @@ | |
| 1 1 |  | 
| 2 2 | 
             
            require 'fileutils'
         | 
| 3 | 
            +
            require 'term/ansicolor'
         | 
| 3 4 |  | 
| 4 | 
            -
             | 
| 5 | 
            +
            module Jkr
         | 
| 5 6 | 
             
              class Env
         | 
| 7 | 
            +
                attr_reader :env_dir
         | 
| 6 8 | 
             
                attr_reader :jkr_dir
         | 
| 7 | 
            -
                attr_reader :working_dir
         | 
| 8 9 | 
             
                attr_reader :jkr_result_dir
         | 
| 9 10 | 
             
                attr_reader :jkr_plan_dir
         | 
| 10 11 | 
             
                attr_reader :jkr_script_dir
         | 
| 11 | 
            -
             | 
| 12 | 
            +
             | 
| 12 13 | 
             
                PLAN_DIR = "plan"
         | 
| 13 14 | 
             
                RESULT_DIR = "result"
         | 
| 14 15 | 
             
                SCRIPT_DIR = "script"
         | 
| 15 16 |  | 
| 16 | 
            -
                def initialize( | 
| 17 | 
            -
                  @ | 
| 18 | 
            -
                  @ | 
| 17 | 
            +
                def initialize(env_dir = Dir.pwd)
         | 
| 18 | 
            +
                  @env_dir = env_dir
         | 
| 19 | 
            +
                  @jkr_dir = File.join(@env_dir, "jkr")
         | 
| 19 20 | 
             
                  @jkr_plan_dir = File.join(@jkr_dir, PLAN_DIR)
         | 
| 20 21 | 
             
                  @jkr_result_dir = File.join(@jkr_dir, RESULT_DIR)
         | 
| 21 22 | 
             
                  @jkr_script_dir = File.join(@jkr_dir, SCRIPT_DIR)
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                   | 
| 23 | 
            +
             | 
| 24 | 
            +
                  unless Dir.exists?(@jkr_dir)
         | 
| 25 | 
            +
                    raise Errno::ENOENT.new(@jkr_dir)
         | 
| 26 | 
            +
                  end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  [@jkr_dir,
         | 
| 29 | 
            +
                   @jkr_result_dir,
         | 
| 30 | 
            +
                   @jkr_plan_dir,
         | 
| 31 | 
            +
                   @jkr_script_dir].each do |dir_path|
         | 
| 24 32 | 
             
                    unless Dir.exists?(dir_path)
         | 
| 25 | 
            -
                       | 
| 33 | 
            +
                      raise ArgumentError.new("Directory #{dir_path} not found")
         | 
| 26 34 | 
             
                    end
         | 
| 27 35 | 
             
                  end
         | 
| 28 36 | 
             
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                def next_plan
         | 
| 31 | 
            -
                  self.plans.first
         | 
| 32 | 
            -
                end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                def plans
         | 
| 35 | 
            -
                  Dir.glob("#{@jkr_plan_dir}#{File::SEPARATOR}*.plan").sort
         | 
| 36 | 
            -
                end
         | 
| 37 37 | 
             
              end
         | 
| 38 38 | 
             
            end
         |