From c2fecde0a04603727949ec0b05d694be89a464d2 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 21 Jan 2008 20:21:07 +0100 Subject: [PATCH] Adding a little script to run benchmarks. it save the data in a marshalled file (in case one of the servers crashes). it tries to be as fair as possible, randomly choosing a setting before running it on each of servers in random order. The other script, benchmark_digest will average up the results of the benchmark and make a little google chart like this http://chart.apis.google.com/chart?chtt=2008.01.21,requests+per+second,74+data+points&chxt=x,x&cht=lxy&chxl=1:|concurrency&chs=500x300&chxp=1,50&chco=dd99dd,dddd99,99dddd&chdl=evented+mongrel|ebb|thin&chd=s:AGLRchnsy39,ttqtlnmjjjl,AGLRchnsy39,9230xv02swz,AGLRchnsy39,1ovwoonqkmm&chxr=0,0,100 --- ruby_binding/benchmark/benchmark_digest.rb | 36 ++++++++ ruby_binding/benchmark/test_camping.rb | 133 +++++++++++++++++++++++++++++ ruby_binding/ebb.rb | 2 +- ruby_binding/test_camping.rb | 41 --------- tcp.c | 2 +- 5 files changed, 171 insertions(+), 43 deletions(-) create mode 100644 ruby_binding/benchmark/benchmark_digest.rb create mode 100755 ruby_binding/benchmark/test_camping.rb delete mode 100755 ruby_binding/test_camping.rb diff --git a/ruby_binding/benchmark/benchmark_digest.rb b/ruby_binding/benchmark/benchmark_digest.rb new file mode 100644 index 0000000..6abd80f --- /dev/null +++ b/ruby_binding/benchmark/benchmark_digest.rb @@ -0,0 +1,36 @@ +# supply the benchmark dump file as an argumetn to this program +require 'rubygems' +require 'google_chart' + +class Array + def avg + sum.to_f / length + end + def sum + inject(0) { |i, s| s += i } + end +end + +colors = [ + '99dddd', + 'dd99dd', + 'dddd99' +].sort_by { rand } + +results = Marshal.load(File.read(ARGV[0])) + +chart = GoogleChart::LineChart.new('500x300', [Time.now.strftime('%Y.%m.%d'), "requests per second", "#{results.length} data points"].join(','), true) +servers = results.map {|r| r[:server] }.uniq +servers.each do |server| + server_data = results.find_all { |r| r[:server] == server } + concurrencies = server_data.map { |d| d[:concurrency] }.uniq + data = [] + concurrencies.each do |c| + measurements = server_data.find_all { |d| d[:concurrency] == c }.map { |d| d[:rps] } + data << [c, measurements.avg] + end + chart.data(server, data.sort, colors.shift) +end +chart.axis(:x, :range => [0,100]) +chart.axis(:x, :labels => ['concurrency'], :positions => [50]) +puts chart.to_url \ No newline at end of file diff --git a/ruby_binding/benchmark/test_camping.rb b/ruby_binding/benchmark/test_camping.rb new file mode 100755 index 0000000..c936cae --- /dev/null +++ b/ruby_binding/benchmark/test_camping.rb @@ -0,0 +1,133 @@ +#!/usr/bin/env ruby +require 'rubygems' +require '../ebb' +require 'camping' +require 'rack' +require 'mongrel' +require 'swiftcore/evented_mongrel' +require 'thin' + +Camping.goes :CampApp +module CampApp + module Controllers + class HW < R('/') + def get + @headers["X-Served-By"] = URI("http://rack.rubyforge.org") + @headers["Content-Type"] = 'text/plain' + "Camping works! " * 5000 + end + def post + "Data: #{input.foo}" + end + end + end +end + +class Array + def avg + sum.to_f / length + end + + def sum + inject(0) { |i, s| s += i } + end + + def rand_each(&block) + sort_by{ rand }.each &block + end +end + + +class ServerTest + attr_reader :name, :port, :app + def initialize(name, port, &start_block) + @name = name + @port = port + puts "Starting #{name}" + @pid = fork { start_block.call } + sleep 3 + end + + def <=>(a) + @name <=> a.name + end + + def kill + Process.kill('KILL', @pid) + end + + def run_trial(concurrency) + print "#{@name} with concurrency #{concurrency}..." + $stdout.flush + r = %x{ab -q -c #{concurrency} -n 1000 http://0.0.0.0:#{@port}/ | grep "Requests per second" } + raise "couldn't match rps in #{r.inspect}" unless r =~ /Requests per second:\s*(\d+\.\d\d)/ + rps = $1.to_f + puts rps + { + :test => 'camping1', + :server=> @name, + :concurrency => concurrency, + :rps => rps, + :time => Time.now + } + end +end + +def all_tests(dump_file = "./benchmarks.ruby_dump") + + if File.readable?(dump_file) + $results = Marshal.load(File.read(dump_file)) + else + $results = [] + end + + app = Rack::Adapter::Camping.new(CampApp) + servers = [] + + servers << ServerTest.new('evented mongrel', 4001) do + ENV['EVENT'] = "1" + Rack::Handler::Mongrel.run(app, :Port => 4001) + end + + servers << ServerTest.new('ebb', 4002) do + server = Ebb::Server.new(app, :Port => 4002) + server.start + end + + servers << ServerTest.new('thin', 4003) do + Rack::Handler::Thin.run(app, :Port => 4003) + end + + + ([1, 10, 19, 28, 37, 46, 55, 64, 73, 82, 91, 100]*3).rand_each do |concurrency| + servers.rand_each do |server| + $results << server.run_trial(concurrency) + sleep 0.5 # give the other process some time to cool down? + end + end + +ensure + puts "killing servers" + servers.each { |server| server.kill } + unless $results.empty? + puts "writing to dump file #{dump_file}" + File.open(dump_file, 'w+') do |f| + f.write Marshal.dump($results) + end + end +end + +all_tests + +# when 'ebb' +# puts "ebb" +# server = Ebb::Server.new(app, :Port => 4001) +# server.start +# # when 'm' +# # puts "mongrel" +# # Rack::Handler::Mongrel.run(app, :Port => 4002) +# when 'mongrel' +# +# else +# puts "unknown arg" +# end \ No newline at end of file diff --git a/ruby_binding/ebb.rb b/ruby_binding/ebb.rb index 98a2671..4933248 100644 --- a/ruby_binding/ebb.rb +++ b/ruby_binding/ebb.rb @@ -1,7 +1,7 @@ # A ruby binding to the ebb web server # Copyright (c) 2007 Ry Dahl # This software is released under the "MIT License". See README file for details. - +$: << File.expand_path(File.dirname(__FILE__)) require 'ebb_ext' module Ebb diff --git a/ruby_binding/test_camping.rb b/ruby_binding/test_camping.rb deleted file mode 100755 index a26a5a0..0000000 --- a/ruby_binding/test_camping.rb +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env ruby -require 'rubygems' -require 'ebb' -require 'camping' -require 'rack' - -Camping.goes :CampApp -module CampApp - module Controllers - class HW < R('/') - def get - @headers["X-Served-By"] = URI("http://rack.rubyforge.org") - "Camping works!" - end - - def post - "Data: #{input.foo}" - end - end - end -end - - -app = Rack::Adapter::Camping.new(CampApp) - -case ARGV[0] -when 'ebb' - puts "ebb" - server = Ebb::Server.new(app, :Port => 4001) - server.start -# when 'm' -# puts "mongrel" -# Rack::Handler::Mongrel.run(app, :Port => 4002) -when 'mongrel' - puts "evented mongrel" - require 'swiftcore/evented_mongrel' - ENV['EVENT'] = "1" - Rack::Handler::Mongrel.run(app, :Port => 4002) -else - puts "unknown arg" -end \ No newline at end of file diff --git a/tcp.c b/tcp.c index b525a19..31bbdcc 100644 --- a/tcp.c +++ b/tcp.c @@ -27,7 +27,7 @@ void tcp_peer_stop_read_watcher(tcp_peer *peer); int tcp_peer_write(tcp_peer *peer, const char *data, int length) { if(!peer->open) { - tcp_warning("Trying to write to a peer that isn't open."); + //tcp_warning("Trying to write to a peer that isn't open."); return 0; } -- 2.11.4.GIT