Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 23, 2012
@gsterndale aget draft 1adda8e
Showing with 173 additions and 17 deletions.
  1. +52 −16 benchmarks/get.rb
  2. +44 −0 examples/aget.rb
  3. +74 −0 lib/reactorb/http.rb
  4. +3 −1 lib/reactorb/reactor.rb
View
68 benchmarks/get.rb
@@ -4,18 +4,21 @@
$: << "#{File.dirname(__FILE__)}/../lib/"
require 'reactorb'
+require 'reactorb/http'
require 'socket'
+require 'uri'
require 'benchmark'
-count = 100
-host = 'www.google.com'
+count = 200
+host = 'localhost'#'www.gregsterndale.com'
port = '80'
request = "GET / HTTP/1.0\r\n\r\n"
+uri = URI.parse("http://#{host}/")
-puts "Serial requests:"
+puts "TCPSockets:"
bytes = ''
-serial_sec = Benchmark.realtime do
+sockets_sec = Benchmark.realtime do
count.times do |i|
io = TCPSocket.open(host, port)
io.write request
@@ -26,10 +29,14 @@
end
end
puts
-puts "Read #{bytes.bytesize} bytes in %.4fsec serially" % serial_sec
+puts "Read #{bytes.bytesize} bytes in %.4fsec just TCPSockets (%.0fbytes/sec)" % [sockets_sec, bytes.bytesize / sockets_sec]
-puts "Reactor:"
+# puts "Threaded requests:"
+# raise "TODO"
+
+
+puts "Reactor TCPSockets:"
bytes = ''
reactor_sec = Benchmark.realtime do
Reactor.run do |reactor|
@@ -48,16 +55,45 @@
end
end
puts
-puts "Read #{bytes.bytesize} bytes in %.4fsec with reactor" % reactor_sec
+puts "Read #{bytes.bytesize} bytes in %.4fsec with reactor and TCPSockets (%.0fbytes/sec)" % [reactor_sec, bytes.bytesize / reactor_sec]
+
+
+puts "Reactor gets:"
+bytes = ''
+gets_sec = Benchmark.realtime do
+Reactor.run do |reactor|
+ include Reactor::HTTP
+ count.times do |i|
+ reactor.get uri do |response|
+ bytes << response
+ print '.'
+ end
+ end
+end
+end
+puts
+puts "Read #{bytes.bytesize} bytes in %.4fsec with reactor gets (%.0fbytes/sec)" % [gets_sec, bytes.bytesize / gets_sec]
+
+
+
+puts "Reactor agets:"
+bytes = ''
+fiber_sec = Benchmark.realtime do
+Reactor.run do |reactor|
+ include Reactor::HTTP
+ (1..count).map{ reactor.aget(uri) }.each{|response| bytes << response; print '.' }
+end
+end
+puts
+puts "Read #{bytes.bytesize} bytes in %.4fsec with reactor fiber gets (%.0fbytes/sec)" % [fiber_sec, bytes.bytesize / fiber_sec]
+results = {
+ 'Serial Socket' => sockets_sec,
+ 'Reactor Socket' => reactor_sec,
+ 'Reactor Serial' => gets_sec,
+ 'Reactor Fiber' => fiber_sec,
+}
-if reactor_sec < serial_sec
- winner = 'Reactor'
- diff = serial_sec-reactor_sec
- percent = (100*diff/serial_sec)
-else
- winner = 'Serial'
- diff = reactor_sec-serial_sec
- percent = (100*diff/reactor_sec)
+results.each do |name, time|
+ puts "#{name}:\t#{time}"
end
-puts "#{winner} was %.2fsec / %.2f%% faster" % [diff, percent]
View
44 examples/aget.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+# encoding: UTF-8
+
+$: << "#{File.dirname(__FILE__)}/../lib/"
+
+require 'reactorb'
+require 'reactorb/http'
+require 'uri'
+
+uri = URI.parse('http://www.google.com/')
+
+serial_responses, responses = []
+
+Reactor.run do |reactor|
+ include Reactor::HTTP
+
+ reactor.get uri do |response1|
+ reactor.get uri do |response2|
+ reactor.get uri do |response3|
+ serial_responses = [response1, response2, response3]
+ if serial_responses.all?{|r| r =~ /200 OK/ }
+ puts "First #{serial_responses.size} serial_responses are OK"
+ reactor.get uri do |response4|
+ serial_responses << response4
+ end
+ end
+ end
+ end
+ end
+
+ responses = (1..3).map{ reactor.aget(uri) }
+ if responses.all?{|r| r =~ /200 OK/ }
+ puts "First #{responses.size} responses are OK"
+ responses << reactor.aget(uri)
+ end
+
+end
+
+puts
+puts "Reactor stopped"
+puts "#{serial_responses.size} serial responses"
+puts "#{responses.size} responses"
+#puts responses.map{|response| response[0..14] }.join("\n")
+
View
74 lib/reactorb/http.rb
@@ -0,0 +1,74 @@
+require 'reactorb'
+require 'socket'
+require 'fiber'
+require 'delegate'
+
+class Reactor
+ module HTTP
+ def get(uri, &handler)
+ host = uri.host
+ port = uri.port
+ io = TCPSocket.open(host, port)
+ bytes = ''
+ self.attach io, :write do |write_io|
+ io.write "GET #{uri.path} HTTP/1.0\r\n\r\n"
+ self.detach(write_io)
+ self.attach io, :read do |read_io|
+ if read_io.eof?
+ read_io.close
+ handler.call(bytes)
+ else
+ # TODO determine performance characteristics
+ # bytes << read_io.read_nonblock(1448)
+ bytes << read_io.read
+ end
+ end
+ end
+ end
+
+ class ADelegator < Delegator
+ def initialize(obj=nil)
+ super
+ @obj_set = !!obj
+ @delegate_sd_obj = obj
+ end
+
+ def __getobj__
+ if !@obj_set
+ @fiber = Fiber.current
+ Fiber.yield
+ end
+ @delegate_sd_obj
+ end
+
+ def __setobj__(obj)
+ @delegate_sd_obj = obj
+ @obj_set = true
+ @fiber.resume if @fiber
+ @delegate_sd_obj
+ end
+ end
+
+ # Fiber gymnastics
+ def aget(uri)
+ delegator = ADelegator.new
+ Fiber.new do
+ f = Fiber.current
+ self.get(uri) {|response| f.resume(response) }
+ delegator.__setobj__ Fiber.yield
+ end.resume
+ return delegator
+ end
+
+
+ def head(uri, &handler)
+ end
+ def delete(uri, &handler)
+ end
+ def put(uri, data, &handler)
+ end
+ def post(uri, data, &handler)
+ end
+ end
+end
+
View
4 lib/reactorb/reactor.rb
@@ -25,7 +25,9 @@ def running?
def run
@running = true
- yield self if block_given?
+ Fiber.new do
+ yield self if block_given?
+ end.resume
while self.running? do
self.tick
self.stop if self.empty?

No commit comments for this range

Something went wrong with that request. Please try again.