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