Feature #8119
closedmore efficient version of Rinda::TupleSpaceProxy.take
Description
=begin
The purpose of Rinda::TupleSpaceProxy is to avoid losing tuples when a client disconnects during a #take call. This is implemented by sending the result value ((twice)): first by pushing it to a client-side array, second by returning the result as a DRb response. If the first fails, then the #take is aborted, so that the tuple is not lost. In case of success, the client only uses the pushed value, not the response value.
This involves a total of ((three)) marshal operations by DRb: the push argument, the push return value (which is an array containing the push argument), and the #take return value. Only the first is necessary.
The following patch adds Rinda::TupleSpaceProxy#take_fast, which avoids the two redundant marshal operations. The unit tests in the ruby source pass when calling this method instead of #take.
The improvement is small when the object is simple. However, for complex objects, eliminating the redundant marshalling reduces network traffic and increases speed by a factor of 2. See the attached bench.rb.
diff --git a/rinda/rinda.rb b/rinda/rinda.rb
index 18e284a..5d280f4 100644
--- a/rinda/rinda.rb
+++ b/rinda/rinda.rb
@@ -206,6 +206,13 @@ module Rinda
# TupleSpaceProxy allows a remote Tuplespace to appear as local.
class TupleSpaceProxy
-
class Port
-
attr_reader :val
-
def push val
-
@val = val
-
nil # so that val doesn't get marshalled again
-
end
-
end
Creates a new TupleSpaceProxy to wrap +ts+.¶
@@ -223,6 +230,17 @@ module Rinda
##
# Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take.
-
This is sometimes a bit faster than #take bacause it uses a version¶
-
of TupleSpace#move that never marshals the result more than once.¶
-
def take_fast(tuple, sec=nil, &block)
-
port = Port.new
-
@ts.move_fast(DRbObject.new(port), tuple, sec, &block)
-
port.val
-
end
-
Takes +tuple+ from the proxied TupleSpace. See TupleSpace#take.¶
def take(tuple, sec=nil, &block)
port = []
diff --git a/rinda/tuplespace.rb b/rinda/tuplespace.rb
index ba494aa..042c605 100644
--- a/rinda/tuplespace.rb
+++ b/rinda/tuplespace.rb
@@ -480,6 +480,43 @@ module Rinda
end -
Moves +tuple+ to +port+, returning nil¶
-
def move_fast(port, tuple, sec=nil)
-
template = WaitTemplateEntry.new(self, tuple, sec)
-
yield(template) if block_given?
-
synchronize do
-
entry = @bag.find(template)
-
if entry
-
port.push(entry.value)
-
@bag.delete(entry)
-
notify_event('take', entry.value)
-
return nil
-
end
-
raise RequestExpiredError if template.expired?
-
begin
-
@take_waiter.push(template)
-
start_keeper if template.expires
-
while true
-
raise RequestCanceledError if template.canceled?
-
raise RequestExpiredError if template.expired?
-
entry = @bag.find(template)
-
if entry
-
port.push(entry.value)
-
@bag.delete(entry)
-
notify_event('take', entry.value)
-
return nil
-
end
-
template.wait
-
end
-
ensure
-
@take_waiter.delete(template)
-
end
-
end
-
end
-
Moves +tuple+ to +port+.¶
def move(port, tuple, sec=nil)
=end
Files