To edit pages or tickets please login with username/password: aaf/aaf

Changeset 285

Show
Ignore:
Timestamp:
11/19/07 22:54:55 (9 months ago)
Author:
jk
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/demo/test/smoke/drb_smoke_test.rb

    r275 r285  
     1require 'rubygems' 
     2require 'gruff' 
     3 
    14# Simple smoke test for the DRb server 
    25# usage:  
     
    1215  RECORDS_PER_PROCESS = 100000 
    1316  NUM_PROCESSES       = 10 # should be an even number 
    14   NUM_RECORDS_PER_LOGENTRY = 10 
    1517  NUM_DOCS = 50 
    1618  NUM_TERMS = 600 
    17  
    18   TIME_FACTOR = 1000.to_f / NUM_RECORDS_PER_LOGENTRY 
     19  START_TIME = Time.now 
    1920 
    2021  class Words 
     
    6566        end 
    6667      end 
     68      def writers_running? 
     69        Dir['*.finished'].size < (NUM_PROCESSES/2) 
     70      end 
    6771      def running? 
    68         Stats.count_by_sql("select count(*) from stats where kind='finished'") < (NUM_PROCESSES/2) 
    69       end 
    70     end 
    71   end 
    72  
    73   class TestBase 
     72        Dir['*.finished'].size < NUM_PROCESSES 
     73      end 
     74    end 
     75  end 
     76 
     77  class WorkerBase 
    7478    def initialize(id) 
    7579      @id = id 
    76       @time = 0 
    77     end 
    78  
     80    end 
     81 
     82    # time since startup in msec 
    7983    def get_time 
    80       returning(Time.now - @t1) do 
    81         @t1 = Time.now 
    82       end 
     84      ((Time.now - START_TIME)*1000).to_i 
    8385    end 
    8486 
     
    8991    end 
    9092 
    91   end 
    92  
    93   class Writer < TestBase 
     93    def log(data) 
     94      data << get_time 
     95      @logfile << data.join(',') << "\n" 
     96    end 
     97 
     98    def log_finished 
     99      File.open("#{@id}.finished", 'w') do |f| 
     100        f << "finished at #{Time.now}\n" 
     101      end 
     102    end 
     103 
     104    def clear_logs 
     105      FileUtils.rm_f "#{@id}.*" 
     106    end 
     107 
    94108    def run 
     109      File.open("#{self.class.prefix}_#{@id}.log",'w') do |f| 
     110        clear_logs 
     111        sleep 1 # allow other processes to get ready 
     112        @logfile = f 
     113        do_run 
     114        log_finished 
     115        puts "#{@id} finished" 
     116      end 
     117    end 
     118 
     119  end 
     120 
     121  class Writer < WorkerBase 
     122    def self.prefix; 'writer' end 
     123    def do_run 
     124      log_interval = RECORDS_PER_PROCESS / 100 
    95125      RECORDS_PER_PROCESS.times do |i| 
    96         @time += benchmark do 
    97           Content.create! :title => "record #{@id} / #{i}", :description => DrbSmokeTest::random_document 
    98         end 
    99         #sleep 0.1 
    100         if i % NUM_RECORDS_PER_LOGENTRY == 0 
    101           # write stats 
    102           puts "#{@id}: #{i} records indexed, last #{NUM_RECORDS_PER_LOGENTRY} in #{@time}" 
    103           Stats.create! :process_id => @id, :kind => 'write', :info => i,  
    104                         :processing_time => @time * TIME_FACTOR,        # average processing time per record in this batch 
    105                         :open_connections => Monitor::count_connections 
    106           @time = 0 
    107         end 
    108       end 
    109       Stats.create! :process_id => @id, :kind => 'finished' 
    110       puts "#{@i} finished" 
    111     end 
    112   end 
    113  
    114   class Searcher < TestBase 
    115     def run 
    116       while Monitor::running? 
     126        log create_record(i) 
     127        if i % log_interval == 0 
     128          # log progress 
     129          puts "#{@id}: #{i} records indexed" 
     130        end 
     131      end 
     132    end 
     133 
     134    def create_record(i) 
     135      time = benchmark do 
     136        Content.create! :title => "record #{@id} / #{i}", :description => DrbSmokeTest::random_document 
     137      end 
     138      [ time ] 
     139    end 
     140  end 
     141 
     142  class Searcher < WorkerBase 
     143    def self.prefix; 'searcher' end 
     144    def do_run 
     145      while Monitor::writers_running? 
    117146        # search with concurrent writes 
    118         do_search 
     147        log do_search 
    119148      end 
    120149      t = Time.now 
    121       while (Time.now - t) < 5.minutes 
     150      while (Time.now - t) < 2.minutes 
    122151        # the writers have finished, now hammer the server with searches for another 5 minutes 
    123         do_search 
    124       end 
    125       puts "#{@i} finished" 
     152        log do_search 
     153      end 
    126154    end 
    127155 
     
    131159    # the word list, ORed together 
    132160    def do_search 
    133       hits = 0 
     161      result = nil 
     162      query = "findme OR #{WORDS.random_word}" 
    134163      time = benchmark do 
    135         NUM_RECORDS_PER_LOGENTRY.times do 
    136           result = Content.find_id_by_contents "findme OR #{WORDS.random_word}" 
    137           hits += result.first 
    138         end 
    139       end 
    140       Stats.create! :process_id => @id, :kind => 'search', :info => "avg total_hits: #{hits/NUM_RECORDS_PER_LOGENTRY.to_f}",  
    141                     :processing_time => time * TIME_FACTOR, 
    142                     :open_connections => Monitor::count_connections 
    143     end 
    144  
     164        result = Content.find_id_by_contents query 
     165      end 
     166      # time, no of hits 
     167      [ time, result.first, query ] 
     168    end 
    145169  end 
    146170 
     
    168192        sleep 10  
    169193      end 
    170     end 
    171   end 
     194      puts "doing the math now..." 
     195      DrbSmokeTest::Stats.new(DrbSmokeTest::Writer::prefix).run 
     196      DrbSmokeTest::Stats.new(DrbSmokeTest::Searcher::prefix).run 
     197    end 
     198  end 
     199 
     200  module Statistics 
     201    def odd?(value) 
     202      value % 2 == 1 
     203    end 
     204 
     205    def median(population) 
     206      if odd?(population.size) 
     207        population[population.size/2] 
     208      else 
     209        mean [ population[population.size/2-1], population[population.size/2] ] 
     210      end 
     211    end 
     212 
     213    def mean(population) 
     214      sum = population.inject(0) { |sum, v| sum + v } 
     215      sum / population.size.to_f 
     216    end 
     217 
     218    # variance and standard_deviation methods from  
     219    # http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/ 
     220    def variance(population) 
     221      n = 0 
     222      mean = 0.0 
     223      s = 0.0 
     224      population.each { |x| 
     225        n = n + 1 
     226        delta = x - mean 
     227        mean = mean + (delta / n) 
     228        s = s + delta * (x - mean) 
     229      } 
     230      # if you want to calculate std deviation 
     231      # of a sample change this to "s / (n-1)" 
     232      return s / n 
     233    end 
     234 
     235    # calculate the standard deviation of a population 
     236    # accepts: an array, the population 
     237    # returns: the standard deviation 
     238    def standard_deviation(population) 
     239      Math.sqrt(variance(population)) 
     240    rescue 
     241      puts "pop: #{population.inspect}" 
     242    end 
     243  end 
     244 
     245  class Stats 
     246    include Statistics 
     247 
     248    def initialize(prefix) 
     249      @prefix = prefix 
     250      @stats = [] 
     251    end 
     252 
     253    def collect_stats 
     254      Dir["#{@prefix}_*.log"].each do |logfile| 
     255        puts logfile 
     256        File.open(logfile) do |f| 
     257          while line = f.gets 
     258            row = line.split(',') 
     259            row[row.size-1] = row.last.to_i 
     260            @stats << row 
     261          end 
     262        end 
     263      end 
     264      puts "#{@stats.size} lines read, now sorting..." 
     265      @stats.sort! { |row1, row2| row1.last <=> row2.last } 
     266    end 
     267 
     268    def with_segments(segment_count) 
     269      t0 = @stats.first.last.to_i 
     270      t1 = @stats.last.last.to_i 
     271      timespan = t1 - t0 
     272      puts "test run took: #{timespan/1000} seconds" 
     273      # we want to draw 1000 points, determine which timespan one point covers 
     274      segment_length = timespan / segment_count 
     275      t = 0 
     276      i = 0 
     277      while t <= t1 
     278        t += segment_length 
     279        segment_stats = [] 
     280        while @stats.any? && @stats.first.last.to_i < t 
     281          segment_stats << @stats.shift 
     282        end 
     283        yield segment_stats unless segment_stats.empty? 
     284      end 
     285    end 
     286 
     287    def run 
     288      collect_stats 
     289      segments = [] 
     290      with_segments(500) do |segment_stats| 
     291        segments << process_segment(segment_stats) 
     292      end 
     293 
     294      chart("#{@prefix} mean", "#{@prefix.downcase}_mean") do |g| 
     295        g.data :mean, segments.map{ |row| row[0] } 
     296        g.data :stddev, segments.map{ |row| row[1] } 
     297      end 
     298      chart("#{@prefix} median", "#{@prefix.downcase}_median") do |g| 
     299        g.data :median, segments.map{ |row| row[2] } 
     300      end 
     301    end 
     302 
     303    def process_segment(segment) 
     304      times = segment.map{|row|row.first.to_i * 1000} 
     305      [mean(times), standard_deviation(times), median(times), segment.size] 
     306    end 
     307 
     308    def chart(title, fname) 
     309      g = Gruff::Line.new do |g| 
     310        g.title = title 
     311        g.theme = { 
     312          :background_colors => ["#e6e6e6", "#e6e6e6"], 
     313          :colors => ["#ff43a7", '#666666', 'black', 'white', 'grey'], 
     314          :marker_color => "white" 
     315        } 
     316      end 
     317      yield g 
     318      g.write "#{fname}.png" 
     319    end 
     320  end 
     321 
    172322end 
    173323 
     324 
    174325DrbSmokeTest::run 
     326 
  • trunk/demo/test/smoke/process_stats.rb

    r275 r285  
    55write = Stats.compute :write 
    66 
    7 def chart(title) 
    8   returning Gruff::Line.new do |g| 
    9     g.title = title 
    10     g.theme = { 
    11       :background_colors => ["#e6e6e6", "#e6e6e6"], 
    12       :colors => ["#ff43a7", '#666666', 'black', 'white', 'grey'], 
    13       :marker_color => "white" 
    14     } 
    15   end 
    16 end 
    177 
    188g = chart "aaf DRb (write performance)" 

To edit pages or tickets please login with username/password: aaf/aaf