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