[roadrunner]ネットワークブロックストレージnbdの読み書き性能をテストする


同時読み書きパフォーマンステストを実行します.
参照
ruby vbd_kv.rb -nbd/dev/nbd0,/dev/nbd1,/dev/nbd2,/dev/nbd3,/dev/nbd4,/dev/nbd5,/dev/nbd6,/dev/nbd7,/dev/nbd8,/dev/nbd9 -size 1073741824
roadrunnerは、入力されたnbdパラメータの数に基づいて、対応するプロセスを独立して異なるnbdにアクセスします.
単一nbd(vm)読み書き性能テスト実行:
参照
ruby vbd_kv.rb -nbd/dev/nbd11 -size 10737418240
require "rubygems"
require File.join(File.dirname(__FILE__),'..','lib','roadrunner')
# require "roadrunner"

#-----------------------------Argv prepare.--------------------------------#

def args(key)
  ARGV.each_with_index do |arg, i|
    return ARGV[i+1] if "-#{key}" == arg
  end
  nil
end

unless args('nbd') && args('size')
  p "[ruby ]#{$0} -nbd /dev/nbd[0-x][,/dev/nbd[0-x],/dev/nbd[0-x]] -size 10240000"
  exit 1
end

#-----------------------------Logger prepare.--------------------------------#

$log ||= Logger.new(STDOUT)

NBD=[]

args('nbd').split(',').each do |n|
  NBD << 
      begin
        f=File.open(n,"rb+")
        f.sync=true
        f
      rescue Exception => e
        $log.error "Can't open #{args('nbd')}!"
        exit -1
      end
end

`echo '' > /root/nbd/sanbo/1.log`

#--------------------------------VBD KV integration test---------------------------------#

class ValidateError < Exception;end

class Kv_vbd
  class << self
    def seq_read(nbd,fs)
      $log.debug("Entry seq_read, ARGV => #{ARGV.inspect}")
      begin
        nbd.rewind# if nbd.eof?
        
        loop {
          #tmp=rand(fs/10000)
          # $log.debug("seq_read:reading #{tmp} bytes from #{nbd}")
          #tmp=nbd.readpartial(tmp)
          #break if nbd.eof?

	  nbd.sysread(1280000)
        }
        
        $log.info("seq_read done.#{fs} bytes read #{nbd}.")
      rescue Exception => e
	if nbd.eof?
	  return nbd.eof?
	else
          $log.error("#{nbd} read error!")
	  raise Exception,e.to_s
	end
      end
      # validate(nbd,fs)
    end

    def seq_write(nbd,fs)
      $log.debug("Entry seq_write, ARGV => #{ARGV.inspect}")
      begin
        nbd.rewind# if nbd.eof?
        
        # bs=1024*1024
        bs=1024
        data='x'*bs
        
        $log.debug("seq_write:writing #{bs} bytes into #{nbd} everytime.")
        
        (fs/bs).times {|t|
          nbd.syswrite(data)
          nbd.flush
          # `sync` if t%10240 == 0
        }
        (nbd.syswrite('x'*(fs%bs));nbd.flush) unless fs%bs == 0
        
        $log.info("ruby io done.sync will exec.")
        `sync`
        # signature(nbd,fs)
        
        $log.info("seq_write done.#{fs} bytes write into #{nbd}.")
      rescue Exception => e
        $log.error("#{nbd} write error!")
      end
      dirty_watcher(nbd,fs)
    end
    
    def signature(nbd,fs)
      $log.debug("Entry signature, ARGV => #{ARGV.inspect}")
      
      nbd.rewind
      nbd.seek(10)
      nbd.syswrite('c')
      
      nbd.seek(-10, IO::SEEK_END)
      nbd.syswrite('c')
      
      begin
        @MD5=`md5sum #{nbd.path}`.match(/(^[a-z0-9A-Z]*)[\s|\t].*$/)[1]
        $log.info("#{nbd.path} md5sum => #{@MD5}")
      rescue Exception => e
        $log.error("md5sum exec error! "+e.to_s)
      end
      
    end
    
    def validate(nbd,fs)
      $log.debug("Entry validate, ARGV => #{ARGV.inspect}")
      
      nbd.rewind
      nbd.seek(10)
      unless (tmp=nbd.sysread(1)) == 'c'
        raise ValidateError,"expect File.seek(10, IO::SEEK_END) => 'c',actually get #{tmp}."
      end
      
      nbd.seek(-10, IO::SEEK_END)
      unless (tmp=nbd.sysread(1)) == 'c'
        raise ValidateError,"expect File.seek(-10, IO::SEEK_END) => 'c',actually get #{tmp}."
      end
      
      
      raise ArgumentError,"No md5sum checked! @MD5 => #{@MD5}" unless @MD5
      _m=`md5sum #{nbd.path}`.match(/(^[a-z0-9A-Z]*)[\s|\t].*$/)[1]
      $log.info("Expect md5sum is #{@MD5}.")
      $log.info("Actually md5sum is #{_m}")
      unless @MD5 == _m
        raise Exception,"md5sum check failed!" 
      end
      
      $log.info("Validate Success...")
    end
    
    # size => get nbd device size used at Linux system
    # return nbd size(Byte)
    # nbd => "/dev/nbd9"
    def size(nbd)
      _s=`ps axf|grep #{nbd}|tail -n1|awk '{print $8}'`.to_i*1024**3
      $log.info("Disk size => #{_s}")
    end
    
    def dirty_watcher(nbd,fs)
      $log.debug("Entry dirty_watcher, ARGV => #{ARGV.inspect}")
      
      dirty=''
      # watch dirty file 10 times,ensure the queue is empty.
      count=10
      begin
        dirty="/tmp/#{`ps axf|grep 'nbd-client .* #{nbd.path}'|tail -n1|awk '{print $9}'`.gsub($/,'')}.dirty"
        loop {
          if IO::read(dirty) == '0'*8
            count-=1
            
            if count == 0
              $log.info("dirty file <#{dirty}> == #{IO::read(dirty)}.Watch over.")
              break
            end
          else
            count=10
          end
          sleep 3
        }
      rescue Exception => e
        $log.error "can't find dirty file => #{dirty}"
        $log.error "ps axf|grep 'nbd-client .* #{nbd.path}' => #{`ps axf|grep 'nbd-client .* #{nbd.path}'`}"
      end
    end
    
  end
end


#--------------------------------RoadRunner---------------------------------#

rr=RoadRunner.new
rr.mode,rr.users,rr.iterations='p',NBD.size,1

rr.log=$log

#['seq_write','signature','seq_read','validate'].each_with_index{|s,i|
#['seq_read'].each_with_index{|s,i|
['seq_write','signature'].each_with_index{|s,i|
  ts_proc=proc{
    # Kv_vbd.send(s,NBD[rr.userId],Kv_vbd.size(NBD[rr.userId].path))
    Kv_vbd.send(s,NBD[rr.userId],args('size').to_i)
  }
  rr.send(s,&ts_proc)
}

rr.run
rr.report

NBD.each{|x|x.close}