class Benchmark::HTTP::Command::Concurrency

Public Instance Methods

call() click to toggle source
# File lib/benchmark/http/command/concurrency.rb, line 119
def call
        @hosts.each do |host|
                run(host).wait
        end
end
confidence_factor() click to toggle source
# File lib/benchmark/http/command/concurrency.rb, line 44
def confidence_factor
        1.0 - @options[:confidence]
end
measure_performance(concurrency, endpoint, request_path) click to toggle source
# File lib/benchmark/http/command/concurrency.rb, line 48
def measure_performance(concurrency, endpoint, request_path)
        puts
        puts "I am running #{concurrency} asynchronous tasks that will each make sequential requests..."
        
        statistics = Statistics.new(concurrency)
        task = Async::Task.current
        
        concurrency.times.map do
                task.async do
                        client = Async::HTTP::Client.new(endpoint, protocol: endpoint.protocol)
                        
                        statistics.sample(confidence_factor) do
                                response = client.get(request_path).tap(&:finish)
                        end
                        
                        client.close
                end
        end.each(&:wait)
        
        puts "I made #{statistics.count} requests in #{Seconds[statistics.sequential_duration]}. The per-request latency was #{Seconds[statistics.latency]}. That's #{statistics.per_second.round(2)} asynchronous requests/second."
        
        puts "\t          Variance: #{Seconds[statistics.variance]}"
        puts "\tStandard Deviation: #{Seconds[statistics.standard_deviation]}"
        puts "\t    Standard Error: #{statistics.standard_error}"
        
        return statistics
end
run(url) click to toggle source
# File lib/benchmark/http/command/concurrency.rb, line 76
def run(url)
        endpoint = Async::HTTP::Endpoint.parse(url)
        request_path = endpoint.url.request_uri
        
        puts "I am going to benchmark #{url}..."
        
        Async::Reactor.run do |task|
                statistics = []
                minimum = @options[:minimum]
                
                base = measure_performance(minimum, endpoint, request_path)
                statistics << base
                
                current = minimum * 2
                maximum = nil
                
                while statistics.last.concurrency < current
                        results = measure_performance(current, endpoint, request_path)
                        
                        if base.similar?(results, @options[:threshold])
                                statistics << results
                                
                                minimum = current
                                
                                if maximum
                                        current += (maximum - current) / 2
                                else
                                        current *= 2
                                end
                        else
                                # current concurrency is too big, so we limit maximum to it.
                                maximum = current
                                
                                current = (minimum + (maximum - minimum) / 2).floor
                        end
                end
                
                puts "Your server can handle #{statistics.last.concurrency} concurrent requests."
                
                puts "At this level of concurrency, requests have ~#{(statistics.last.latency / statistics.first.latency).round(2)}x higher latency."
        end
end