<commit_before>
module Stella::Engine
  module Stress
    extend Stella::Engine::Base
    extend self
    
    @timers = [:do_request]
    @counts = [:response_content_size]
    
    class << self
      attr_accessor :timers, :counts
    end
    
    def run(plan, opts={})
      process_options! plan, opts
      
      if Stella.loglev > 1
        Stress.timers += [:connect, :create_socket, :query, :socket_gets_first_byte, :get_body]
        Stress.counts  = [:request_header_size, :request_content_size]
        Stress.counts += [:response_headers_size, :response_content_size]
      end
      
      counts = calculate_usecase_clients plan, opts
      
      Stella.li $/, "Preparing #{counts[:total]} virtual clients...", $/
      Stella.lflush
      packages = build_thread_package plan, opts, counts
      
      Stella.li "Generating load...", $/
      Stella.lflush
      
      begin
        execute_test_plan packages, opts[:repetitions]
      rescue Interrupt
        Stella.li "Stopping test...", $/
        Stella.abort!
      ensure
        Stella.li "Processing statistics...", $/
        Stella.lflush
        
        wait_for_reporter
        
        tt = Benelux.thread_timeline
        test_time = tt.stats.group(:execute_test_plan).mean
        
        generate_report plan, test_time
        
        Stella.li "Overall time: "
        Stella.li "  prep: %10.2fs" % tt.stats.group(:build_thread_package).mean
        Stella.li "  test: %10.2fs" % test_time
        Stella.li "  wait: %10.2fs" % tt.stats.group(:wait_for_reporter).mean
        Stella.li "  post: %10.2fs" % tt.stats.group(:generate_report).mean
        Stella.li $/
      end
      
      # errors?
    end
    
    def wait_for_reporter
      Benelux.reporter.wait
    end
    
  protected
    class ThreadPackage
      attr_accessor :index
      attr_accessor :client
      attr_accessor :usecase
      def initialize(i, c, u)
        @index, @client, @usecase = i, c, u
      end
    end
    
    def calculate_usecase_clients(plan, opts)
      counts = { :total => 0 }
      plan.usecases.each_with_index do |usecase,i|
        count = case opts[:clients]
        when 0..9
          if (opts[:clients] % plan.usecases.size > 0) 
            msg = "Client count does not evenly match usecase count"
            raise Stella::Testplan::WackyRatio, msg
          else
            (opts[:clients] / plan.usecases.size)
          end
        else
          (opts[:clients] * usecase.ratio).to_i
        end
        counts[usecase.digest_cache] = count
        counts[:total] += count
      end
      counts
    end
    
    def build_thread_package(plan, opts, counts)
      packages, pointer = Array.new(counts[:total]), 0
      plan.usecases.each do |usecase|
        count = counts[usecase.digest_cache]
        Stella.ld "THREAD PACKAGE: #{usecase.desc} (#{pointer} + #{count})"
        # Fill the thread_package with the contents of the block
        packages.fill(pointer, count) do |index|
          Stella.li3 "Creating client ##{index+1} "
          client = Stella::Client.new opts[:hosts].first, index+1
          client.add_observer(self)
          client.enable_nowait_mode 
          ThreadPackage.new(index+1, client, usecase)
        end
        pointer += count
      end
      packages.compact # TODO: Why one nil element sometimes?
    end
    
    def execute_test_plan(packages, reps=1)
      Thread.ify packages, :threads => packages.size do |package|
        # This thread will stay on this one track. 
        Benelux.current_track package.client.gibbler
        Benelux.add_thread_tags :usecase => package.usecase.digest_cache
        (1..reps).to_a.each do |rep|
          Benelux.add_thread_tags :rep =>  rep
          Stella::Engine::Stress.rescue(package.client.digest_cache) {
            break if Stella.abort?
            print '.' if Stella.loglev == 2
            stats = package.client.execute package.usecase
          }
          Benelux.remove_thread_tags :rep
        end
        
        Benelux.remove_thread_tags :usecase
        
      end
      Stella.li2 $/, $/
    end
      
    def generate_report(plan,test_time)
      #Benelux.update_all_track_timelines
      global_timeline = Benelux.timeline
      
      Stella.li $/, " %-72s  ".att(:reverse) % ["#{plan.desc}  (#{plan.digest_cache.shorter})"]
      plan.usecases.uniq.each_with_index do |uc,i| 
        
        # TODO: Create Ranges object, like Stats object
        # global_timeline.ranges(:do_request)[:usecase => '1111']
        # The following returns globl do_request ranges. 
        requests = 0 #global_timeline.ranges(:do_request).size
        
        desc = uc.desc || "Usecase ##{i+1} "
        desc << "  (#{uc.digest_cache.shorter}) "<commit_msg>Added marginal sleep between client reps<commit_after>
module Stella::Engine
  module Stress
    extend Stella::Engine::Base
    extend self
    
    @timers = [:do_request]
    @counts = [:response_content_size]
    
    class << self
      attr_accessor :timers, :counts
    end
    
    def run(plan, opts={})
      process_options! plan, opts
      
      if Stella.loglev > 1
        Stress.timers += [:connect, :create_socket, :query, :socket_gets_first_byte, :get_body]
        Stress.counts  = [:request_header_size, :request_content_size]
        Stress.counts += [:response_headers_size, :response_content_size]
      end
      
      counts = calculate_usecase_clients plan, opts
      
      Stella.li $/, "Preparing #{counts[:total]} virtual clients...", $/
      Stella.lflush
      packages = build_thread_package plan, opts, counts
      
      Stella.li "Generating load...", $/
      Stella.lflush
      
      begin
        execute_test_plan packages, opts[:repetitions]
      rescue Interrupt
        Stella.li "Stopping test...", $/
        Stella.abort!
      ensure
        Stella.li "Processing statistics...", $/
        Stella.lflush
        
        wait_for_reporter
        
        tt = Benelux.thread_timeline
        test_time = tt.stats.group(:execute_test_plan).mean
        
        generate_report plan, test_time
        
        Stella.li "Overall time: "
        Stella.li "  prep: %10.2fs" % tt.stats.group(:build_thread_package).mean
        Stella.li "  test: %10.2fs" % test_time
        Stella.li "  wait: %10.2fs" % tt.stats.group(:wait_for_reporter).mean
        Stella.li "  post: %10.2fs" % tt.stats.group(:generate_report).mean
        Stella.li $/
      end
      
      # errors?
    end
    
    def wait_for_reporter
      Benelux.reporter.wait
    end
    
  protected
    class ThreadPackage
      attr_accessor :index
      attr_accessor :client
      attr_accessor :usecase
      def initialize(i, c, u)
        @index, @client, @usecase = i, c, u
      end
    end
    
    def calculate_usecase_clients(plan, opts)
      counts = { :total => 0 }
      plan.usecases.each_with_index do |usecase,i|
        count = case opts[:clients]
        when 0..9
          if (opts[:clients] % plan.usecases.size > 0) 
            msg = "Client count does not evenly match usecase count"
            raise Stella::Testplan::WackyRatio, msg
          else
            (opts[:clients] / plan.usecases.size)
          end
        else
          (opts[:clients] * usecase.ratio).to_i
        end
        counts[usecase.digest_cache] = count
        counts[:total] += count
      end
      counts
    end
    
    def build_thread_package(plan, opts, counts)
      packages, pointer = Array.new(counts[:total]), 0
      plan.usecases.each do |usecase|
        count = counts[usecase.digest_cache]
        Stella.ld "THREAD PACKAGE: #{usecase.desc} (#{pointer} + #{count})"
        # Fill the thread_package with the contents of the block
        packages.fill(pointer, count) do |index|
          Stella.li3 "Creating client ##{index+1} "
          client = Stella::Client.new opts[:hosts].first, index+1
          client.add_observer(self)
          client.enable_nowait_mode 
          ThreadPackage.new(index+1, client, usecase)
        end
        pointer += count
      end
      packages.compact # TODO: Why one nil element sometimes?
    end
    
    def execute_test_plan(packages, reps=1)
      Thread.ify packages, :threads => packages.size do |package|
        # This thread will stay on this one track. 
        Benelux.current_track package.client.gibbler
        Benelux.add_thread_tags :usecase => package.usecase.digest_cache
        (1..reps).to_a.each do |rep|
          Benelux.add_thread_tags :rep =>  rep
          Stella::Engine::Stress.rescue(package.client.digest_cache) {
            break if Stella.abort?
            print '.' if Stella.loglev == 2
            stats = package.client.execute package.usecase
          }
          Benelux.remove_thread_tags :rep
          sleep 0.001
        end
        
        Benelux.remove_thread_tags :usecase
        
      end
      Stella.li2 $/, $/
    end
      
    def generate_report(plan,test_time)
      #Benelux.update_all_track_timelines
      global_timeline = Benelux.timeline
      
      Stella.li $/, " %-72s  ".att(:reverse) % ["#{plan.desc}  (#{plan.digest_cache.shorter})"]
      plan.usecases.uniq.each_with_index do |uc,i| 
        
        # TODO: Create Ranges object, like Stats object
        # global_timeline.ranges(:do_request)[:usecase => '1111']
        # The following returns globl do_request ranges. 
        requests = 0 #global_timeline.ranges(:do_request).size
        
        desc = uc.desc || "Usecase ##{i+1} "
        desc << "  (#{uc.digest_cache.shorter}) "
{'fraction_non_alphanumeric': 0.10460863204096561, 'fraction_numerical': 0.007524297209739785, 'mean_word_length': 2.0841121495327104, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '939912', 'n_tokens_mistral': 3059, 'n_tokens_neox': 3042, 'n_words': 641}