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 12 years ago
          Updated by zzak (zzak _) over 12 years ago
          
          
        
        
      
      - Status changed from Open to Assigned
- Assignee set to seki (Masatoshi Seki)
        
           Updated by drbrain (Eric Hodel) over 12 years ago
          Updated by drbrain (Eric Hodel) over 12 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 12 years ago
          Updated by drbrain (Eric Hodel) over 12 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 12 years ago
          Updated by seki (Masatoshi Seki) over 12 years ago
          
          
        
        
      
      - Assignee changed from seki (Masatoshi Seki) to drbrain (Eric Hodel)
        
           Updated by naruse (Yui NARUSE) over 12 years ago
          Updated by naruse (Yui NARUSE) over 12 years ago
          
          
        
        
      
      Just FYI, you can use =begin ... =end for commenting out multiline
        
           Updated by drbrain (Eric Hodel) over 12 years ago
          Updated by drbrain (Eric Hodel) over 12 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.