Module: RoadRunnerModule

Included in:
RoadRunner
Defined in:
lib/run.rb,
lib/db.rb,
lib/init.rb,
lib/ended.rb,
lib/action.rb,
lib/report.rb,
lib/rrhelper.rb,
lib/rrmonitor.rb

Overview

Rrhelper will include many helpful methods for RoadRunner

Defined Under Namespace

Modules: Dbhelper, Rrhelper Classes: RRMonitor

Instance Method Summary collapse

Instance Method Details

#action(&blk) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/action.rb', line 4

def action(&blk)

  if block_given?
    @actBlk=blk
    register_transactions('actoin',&blk)
  else
    raise ArgumentError, "no block"
  end

end

#ended(&blk) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/ended.rb', line 4

def ended(&blk)

  if block_given?
    @endBlk=blk
    register_transactions('end',&blk)
  else
    raise ArgumentError, "no block"
  end

end

#init(&blk) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/init.rb', line 4

def init(&blk)

  if block_given?
    @initBlk=blk
    register_transactions('init',&blk)
  else
    raise ArgumentError, "no block"
  end

end

#iterationIdObject



5
6
7
8
9
10
11
# File 'lib/rrhelper.rb', line 5

def iterationId
  if(@mode=='thread')then
    @thread_pool[Thread.current][:iterationId]
  else
    @iterationId
  end
end

#report(opts = {:label=>'',:width=>0,:msg=>""}) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/report.rb', line 6

def report(opts={:label=>'',:width=>0,:msg=>""})
  p "      Wait for moment,the report is collecting......"
  content = if @rep
    @succRates = getSuccessRate @transactions
    <<-DOC
    #{"Performance Reports".center(50, '*')}
    #{opts[:label].ljust(opts[:width])}
    #{Benchmark::Tms::CAPTION}
    #{@rep.format}
    #{'--'*32}
    The Virtual User is #{@users}.
    Total Execute #{@iterations*@users} Action(s).
    Total Cost #{@rep.real} Second(s).
    This Scenario's TPS : #{@tps}.
    The longest action cost #{@longest || 0} seconds.
    #{'Transaction Report'.center(50, '-')}
    #{@transactions.inject("") { |str,k|
    str += "#{k[0].to_s} : count => #{k[1].size} time(s) , cost => #{k[1].inject(0){|c,v|c+=v[:cost].to_f}.to_s[0..3]} sec(s) , success rate => #{@succRates[k[0]]}\n      "
    }.gsub(/\n$/,'')}
    #{'--'*32}
    User defined params as below: 
    #{@global}
    #{"End of Reports".center(50, '*')}
    DOC
  else
    "None Report before RoadRunner run."
  end
  puts content
  self.log.info content
end

#runObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/run.rb', line 5

def run
  @strat_time = Time.now
  @initBlk.call
  @thread_pool = {}
  @counter = 0

  @log.debug "Mode => #{@mode}"
  
  # >> Benchmark.bm {|x|x.report{(1..10).to_a.max}}
  #       user     system      total        real
  #   0.000000   0.000000   0.000000 (  0.000034)
  # => true
  # >> Benchmark.bm {|x|x.report{(1..100).to_a.max}}
  #       user     system      total        real
  #   0.000000   0.000000   0.000000 (  0.000214)
  # => true
  # >> Benchmark.bm {|x|x.report{(1..1000).to_a.max}}
  #       user     system      total        real
  #   0.000000   0.000000   0.000000 (  0.002074)
  # => true
  # >> Benchmark.bm {|x|x.report{(1..1000000).to_a.max}}
  #       user     system      total        real
  #   1.030000   0.670000   1.700000 (  1.766415)
  # => true
  
  iterationBlk = case @mode
  when /thread/,/t/ then
    proc {      
      @users.times do |userId|
        @thread_pool[Thread.start(){
          @iterations.times do |iterationId|
            
            rcost = []
            @transaction_blk.each_pair{|k,v|
              rcost << self.transaction(k,&v)
            }
            
            # rcost = self.transaction('Action',&@actBlk)
            # @log.debug "IterationID is #{self.iterationId};UserID is #{self.userId};This Action Cost #{rcost} seconds"
            @longest = (@longest<rcost.max) ? rcost.max : @longest
            @thread_pool[Thread.current][:iterationId] = iterationId
          end
          @counter += 1
        }]={:userId=>userId}
      end
     # @thread_pool.keys.each{|t|t.join}
      while @counter != @users do
        Thread.pass
      end
    }
  when /process/,/p/ then
    proc {
      ppid=Process.pid
      # @log.info("Main Process pid => #{ppid}")
      
      pids=[]
      @users.times { |userId|
        pids << Process.fork { 
          rcost = {}
          @userId=userId
          @iterations.times do |iterationId|
            @iterationId=iterationId
            
            @transaction_blk.each_pair{|k,v|
              rcost[k]=[] unless rcost[k]
              rcost[k] << self.transaction(k,&v)
              # self.log.info("rcost => #{rcost.inspect}")
            }
            
          end
          
          # >> r
          # => {:y=>[2, 1, 5, 9], :x=>[1, 2, 3, 4]}
          # >> r.map{|x|{x[0]=>x[1].max}}
          # => [{:y=>9}, {:x=>4}]
          m=0
          rcost.map{|x|{x[0]=>x[1].max}}.each{|h|
           if(h.values[0]>m) 
             @longest=h
           end
          }
          
          succRates = getSuccessRate @transactions
          
          preport=
<<-DOC
<PID:#{Process.pid}> <UserId:#{@userId}>
#{'Process Transaction Report'.center(50, '-')}
#{@transactions.inject("") { |str,k|
str += "#{k[0].to_s} : count => #{k[1].size} time(s) , cost => #{k[1].inject(0){|c,v|c+=v[:cost].to_f}.to_s[0..3]} sec(s) , success rate => #{succRates[k[0]]}#{$/}"
}.gsub(/\n$/,'')}
#{'--'*32}
DOC
          self.log.info(preport)
          puts(preport)
          
          # @log.info @longest.inspect
          @log.info("<PID:#{Process.pid}> going down.Longest job(#{@longest.keys[0]}) cost #{@longest.values[0]}")
          p ("<PID:#{Process.pid}> going down.Longest job(#{@longest.keys[0]}) cost #{@longest.values[0]}")
          
          Process.kill("HUP", ppid)
        }
      }
      
      switch=true
      c=0
      Signal.trap("HUP", proc { @log.info("One User(Process) done."); (switch = false;p "Main process<#{Process.pid}> going down.") if ((c+=1) == @users) })
      
      @log.info "Waiting Processes => #{pids.inspect}"
      
      p "Processes<#{pids.inspect}> working."
      while switch
        STDOUT.puts '.'
        sleep 5
      end
      p $/
      
      Process.waitall
      @log.info "Processes down."
    }
  else
    proc {
      @iterations.times do |iterationId|
        @iterationId=iterationId
        @users.times do |userId|
          @userId=userId
          
          rcost = []
          @transaction_blk.each_pair{|k,v|
            rcost << self.transaction(k,&v)
          }
          
          # rcost = self.transaction('Action',&@actBlk)
          
          # => the below sentence cost a lot of system resource
          # => if you run for production result,keep it annotated!!!
#          self.log.debug "IterationID is #{self.iterationId};UserID is #{self.userId};This Action Cost #{rcost} seconds"
          @longest = (@longest<rcost.max) ? rcost.max : @longest
        end
      end
    }
  end

  p '      '+"RoadRunner".center(50, '*')
  p '      *'+"---Run , on your way.".rjust(48, ' ')+'*'
  p '      '+'*'*50
  p
  p "      Running......"
  @rep = Benchmark::measure(&iterationBlk)
  p "      Ending......"
  @endBlk.call

  @tps = @iterations*@users/@rep.real
end

#save_report(opts = {:author=>'Anonymous',:script=>""}) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
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
76
77
78
79
80
81
82
83
84
# File 'lib/report.rb', line 37

def save_report(opts={:author=>'Anonymous',:script=>""})

  p "      Saving report to database......"
  opts={:author=>'Anonymous',:script=>""}.merge opts
  if @data_write then
    unless opts[:name] then
      self.log.warn "scenario name may be needed."
      require 'uuidtools' unless defined?UUID
      # scenario || UUID.random_create.to_s is for debug
      opts[:name] = opts[:name] || UUID.random_create.to_s
      self.log.info "scenario is created as #{opts[:name]}"
    end
    # => scenario = Scenario.find_or_create_by_name(opts.merge({:create_at=>Time.now})).shift
    scenario = Scenario.find_or_create_by_name(opts.merge({:create_at=>Time.now}))
    scenario.tps+=@iterations*@users/@rep.real

    # => if opts[:script] is set as <your script>.rb 's path
    # => opts[:script] = __FILE__
    # => then scenario.script will be set.
    if FileTest.exist?(opts[:script]) then
      scenario.script = ""
      IO.foreach(opts[:script]){|x|scenario.script << x}
    end

    @succRates = @succRates || (getSuccessRate @transactions)
    # k is transaction name ,
    # v is reports in every transaction.
    @transactions.each do |k,v|
      transaction  = Transaction.new({:name=>k,:create_at=>Time.now,:success_rate=>@succRates[k]})
      v.each_index do |id|
        transaction.records << Record.new(v[id].merge({:seq=>id,:ts=>v[id][:create_at].to_f-@strat_time.to_f}))
        self.log.debug "v[#{id}] = #{v[id].inspect}"
      end
      scenario.transactions << transaction
    end
    begin
      scenario.save!
      p "      Saved OK!"
    rescue =>e
      self.log.error e
      p e
    end
    self.log.info "records has saved in DB."
  else
    p '      Error:You didn\'t connect any database.'
    self.log.error 'You didn\'t connect any database.'
  end
end

#userIdObject



13
14
15
16
17
18
19
# File 'lib/rrhelper.rb', line 13

def userId
  if(@mode=='thread')then
    @thread_pool[Thread.current][:userId]
  else
    @userId
  end
end