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
Updated by zzak (zzak _) over 11 years ago
- Status changed from Open to Assigned
- Assignee set to seki (Masatoshi Seki)
Updated by drbrain (Eric Hodel) over 11 years ago
- Priority changed from 3 to Normal
I think #8125 should be applied, then a new patch be generated for this issue.
Updated by drbrain (Eric Hodel) over 11 years ago
- File rinda.rb.8119.patch rinda.rb.8119.patch added
With #8125, your benchmark is 40% faster +/- 2% at 95% confidence.
With #8119, your benchmark is ~120% faster, but the tests fail as #take calls #move with a port of nil, so local users of the TupleSpace will experience a behavior change.
I've updated your patch to have the same speed gains while maintaining backwards compatibility. The attached patch, compared to rinda in ruby 2.0.0p57 is 120% faster +/- 2.4% at 95% confidence.
Updated by seki (Masatoshi Seki) over 11 years ago
- Assignee changed from seki (Masatoshi Seki) to drbrain (Eric Hodel)
Updated by naruse (Yui NARUSE) over 11 years ago
Just FYI, you can use =begin ... =end for commenting out multiline
Updated by drbrain (Eric Hodel) over 11 years ago
- Status changed from Assigned to Closed
- % Done changed from 0 to 100
This issue was solved with changeset r39923.
Joel, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.