ffi-rzmq 0.9.3 → 0.9.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +51 -0
 - data/README.rdoc +17 -7
 - data/examples/v2api/local_lat_poll.rb +3 -3
 - data/examples/v2api/local_throughput.rb +2 -2
 - data/examples/v2api/pub.rb +46 -0
 - data/examples/v2api/publish_subscribe.rb +1 -1
 - data/examples/v2api/remote_throughput.rb +1 -1
 - data/examples/v2api/reqrep_poll.rb +2 -2
 - data/examples/v2api/request_response.rb +2 -2
 - data/examples/v2api/sub.rb +74 -0
 - data/examples/v2api/throughput_measurement.rb +3 -3
 - data/examples/v2api/xreqxrep_poll.rb +5 -5
 - data/examples/v3api/local_lat_poll.rb +3 -3
 - data/examples/v3api/pub.rb +46 -0
 - data/examples/v3api/publish_subscribe.rb +1 -1
 - data/examples/v3api/reqrep_poll.rb +2 -2
 - data/examples/v3api/sub.rb +69 -0
 - data/examples/v3api/xreqxrep_poll.rb +5 -5
 - data/ffi-rzmq.gemspec +2 -2
 - data/lib/ffi-rzmq/constants.rb +56 -18
 - data/lib/ffi-rzmq/context.rb +63 -24
 - data/lib/ffi-rzmq/device.rb +19 -19
 - data/lib/ffi-rzmq/libzmq.rb +109 -34
 - data/lib/ffi-rzmq/message.rb +23 -2
 - data/lib/ffi-rzmq/poll.rb +7 -9
 - data/lib/ffi-rzmq/socket.rb +284 -518
 - data/lib/ffi-rzmq/util.rb +42 -36
 - data/lib/ffi-rzmq/version.rb +1 -1
 - data/spec/context_spec.rb +20 -16
 - data/spec/device_spec.rb +64 -76
 - data/spec/multipart_spec.rb +0 -54
 - data/spec/nonblocking_recv_spec.rb +119 -80
 - data/spec/poll_spec.rb +93 -12
 - data/spec/pushpull_spec.rb +65 -111
 - data/spec/reqrep_spec.rb +45 -56
 - data/spec/socket_spec.rb +104 -71
 - data/spec/spec_helper.rb +52 -4
 - metadata +155 -135
 
    
        data/History.txt
    CHANGED
    
    | 
         @@ -1,3 +1,52 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            == 0.9.6 / 20120808
         
     | 
| 
      
 2 
     | 
    
         
            +
              * Never released 0.9.5 as a gem. It was available via github only.
         
     | 
| 
      
 3 
     | 
    
         
            +
              
         
     | 
| 
      
 4 
     | 
    
         
            +
              * Improved error message when DLL loading fails on Windows.
         
     | 
| 
      
 5 
     | 
    
         
            +
              
         
     | 
| 
      
 6 
     | 
    
         
            +
              * Added support for 0mq 2.2. Support for 2.1 might be getting shakey...
         
     | 
| 
      
 7 
     | 
    
         
            +
                patches to make it fully support 2.1 (assuming it's even broken at
         
     | 
| 
      
 8 
     | 
    
         
            +
                all) are welcome.
         
     | 
| 
      
 9 
     | 
    
         
            +
              
         
     | 
| 
      
 10 
     | 
    
         
            +
              * Added support for 0mq 3.2 (no support for 3.0 or 3.1). Not all methods
         
     | 
| 
      
 11 
     | 
    
         
            +
                are exposed yet. For example, setting values on the context after it
         
     | 
| 
      
 12 
     | 
    
         
            +
                has been created is not supported; instead, pass the correct keys
         
     | 
| 
      
 13 
     | 
    
         
            +
                (:io_threads and :max_sockets) to the call to Context.create or
         
     | 
| 
      
 14 
     | 
    
         
            +
                Context#new.
         
     | 
| 
      
 15 
     | 
    
         
            +
                
         
     | 
| 
      
 16 
     | 
    
         
            +
              * Reduced spec running time from 30+ seconds to under 1 by eliminating
         
     | 
| 
      
 17 
     | 
    
         
            +
                most uses of "sleep." It now polls sockets to wait for message
         
     | 
| 
      
 18 
     | 
    
         
            +
                delivery. It also uses a technique of binding an inproc transport and
         
     | 
| 
      
 19 
     | 
    
         
            +
                busy-looping on the connect side until it succeeds. These techniques
         
     | 
| 
      
 20 
     | 
    
         
            +
                both allowed me to eliminate most uses of sleep.
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
              * Some changes to support usage on Win7x64 with a 64-bit libzmq DLL.
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            == 0.9.5 / 20120119
         
     | 
| 
      
 25 
     | 
    
         
            +
              * BROKE THE API.
         
     | 
| 
      
 26 
     | 
    
         
            +
                In 0mq 2.x, there were two functions zmq_send() and zmq_recv().
         
     | 
| 
      
 27 
     | 
    
         
            +
                As of 3.x, those functions were renamed zmq_sendmsg() and
         
     | 
| 
      
 28 
     | 
    
         
            +
                zmq_recvmsg(). As everyone starts moving to 0mq 3.x, it doesn't
         
     | 
| 
      
 29 
     | 
    
         
            +
                make sense to make the code break with 2.x. So, I'm breaking this
         
     | 
| 
      
 30 
     | 
    
         
            +
                binding so that it always uses sendmsg/recvmsg and eliminates the
         
     | 
| 
      
 31 
     | 
    
         
            +
                original send/recv methods.
         
     | 
| 
      
 32 
     | 
    
         
            +
                Sorry!
         
     | 
| 
      
 33 
     | 
    
         
            +
                This is likely to be the last non-backward-compatible API breakage.
         
     | 
| 
      
 34 
     | 
    
         
            +
                Release 1.0 is around the corner and the API will be stable (I follow
         
     | 
| 
      
 35 
     | 
    
         
            +
                semantic versioning).
         
     | 
| 
      
 36 
     | 
    
         
            +
                
         
     | 
| 
      
 37 
     | 
    
         
            +
              * Introduced ZMQ::NonBlocking. This flag returns the correct value to set
         
     | 
| 
      
 38 
     | 
    
         
            +
                a socket in non-blocking mode when sending/receiving. This hides the
         
     | 
| 
      
 39 
     | 
    
         
            +
                differences between 0mq 2.x and 3.x since the constant names have
         
     | 
| 
      
 40 
     | 
    
         
            +
                changed.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            == 0.9.4 / 20120102
         
     | 
| 
      
 43 
     | 
    
         
            +
              * Fixed bug in Poller#delete. Added specs to catch a regression.
         
     | 
| 
      
 44 
     | 
    
         
            +
                In short, a socket that was deleted from the Poller set wasn't
         
     | 
| 
      
 45 
     | 
    
         
            +
                always actually *removed* from the array. This led to a closed
         
     | 
| 
      
 46 
     | 
    
         
            +
                socket being part of the pollset which would return errno 38.
         
     | 
| 
      
 47 
     | 
    
         
            +
                This took about 4 days to find. <sigh>
         
     | 
| 
      
 48 
     | 
    
         
            +
                
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
       1 
50 
     | 
    
         
             
            == 0.9.3 / 20111214
         
     | 
| 
       2 
51 
     | 
    
         
             
              * Performance optimizations for #getsockopt.
         
     | 
| 
       3 
52 
     | 
    
         | 
| 
         @@ -15,6 +64,8 @@ 
     | 
|
| 
       15 
64 
     | 
    
         
             
                can avoid that work and dispatch directly. This effects all
         
     | 
| 
       16 
65 
     | 
    
         
             
                Ruby runtimes, but it was through the work of Evan Phoenix that
         
     | 
| 
       17 
66 
     | 
    
         
             
                I figured this out. Results in a 2-5% speedup on method dispatch.
         
     | 
| 
      
 67 
     | 
    
         
            +
                
         
     | 
| 
      
 68 
     | 
    
         
            +
              
         
     | 
| 
       18 
69 
     | 
    
         | 
| 
       19 
70 
     | 
    
         
             
            == 0.9.2 / 20111115
         
     | 
| 
       20 
71 
     | 
    
         
             
              * Removed all references to the version4 API.
         
     | 
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -54,6 +54,14 @@ shouting but I wanted to make sure this stood out. 
     | 
|
| 
       54 
54 
     | 
    
         | 
| 
       55 
55 
     | 
    
         
             
            All example code has been updated to use the new Ruby API.
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
      
 57 
     | 
    
         
            +
            == Breaking API Change from 0.9.3 to 0.9.5
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            The 0mq library functions zmq_send() and zmq_recv() were changed to 
         
     | 
| 
      
 60 
     | 
    
         
            +
            zmq_sendmsg() and zmq_recvmsg() with the 0mq 3.x API change. I have changed
         
     | 
| 
      
 61 
     | 
    
         
            +
            the binding to always use #sendmsg and #recvmsg. This breaks existing code.
         
     | 
| 
      
 62 
     | 
    
         
            +
            This should be the last breaking change heading into the 1.0 release of these
         
     | 
| 
      
 63 
     | 
    
         
            +
            bindings.
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
       57 
65 
     | 
    
         
             
            == PERFORMANCE
         
     | 
| 
       58 
66 
     | 
    
         | 
| 
       59 
67 
     | 
    
         
             
            Check out the latest performance results:
         
     | 
| 
         @@ -93,13 +101,14 @@ All features are implemented. 
     | 
|
| 
       93 
101 
     | 
    
         | 
| 
       94 
102 
     | 
    
         
             
              ctx = ZMQ::Context.new
         
     | 
| 
       95 
103 
     | 
    
         
             
              s = ctx.socket ZMQ::REP
         
     | 
| 
       96 
     | 
    
         
            -
              s.setsockopt(ZMQ::HWM, 100)
         
     | 
| 
       97 
     | 
    
         
            -
              s.bind(bind_to)
         
     | 
| 
      
 104 
     | 
    
         
            +
              rc = s.setsockopt(ZMQ::HWM, 100)
         
     | 
| 
      
 105 
     | 
    
         
            +
              rc = s.bind(bind_to)
         
     | 
| 
       98 
106 
     | 
    
         | 
| 
      
 107 
     | 
    
         
            +
              msg = ""
         
     | 
| 
       99 
108 
     | 
    
         
             
              roundtrip_count.times do
         
     | 
| 
       100 
     | 
    
         
            -
                 
     | 
| 
      
 109 
     | 
    
         
            +
                rc = s.recv_string msg
         
     | 
| 
       101 
110 
     | 
    
         
             
                raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
         
     | 
| 
       102 
     | 
    
         
            -
                s.send_string msg, 0
         
     | 
| 
      
 111 
     | 
    
         
            +
                rc = s.send_string msg, 0
         
     | 
| 
       103 
112 
     | 
    
         
             
              end
         
     | 
| 
       104 
113 
     | 
    
         | 
| 
       105 
114 
     | 
    
         | 
| 
         @@ -119,15 +128,16 @@ All features are implemented. 
     | 
|
| 
       119 
128 
     | 
    
         | 
| 
       120 
129 
     | 
    
         
             
              ctx = ZMQ::Context.new
         
     | 
| 
       121 
130 
     | 
    
         
             
              s = ctx.socket ZMQ::REQ
         
     | 
| 
       122 
     | 
    
         
            -
              s.connect(connect_to)
         
     | 
| 
      
 131 
     | 
    
         
            +
              rc = s.connect(connect_to)
         
     | 
| 
       123 
132 
     | 
    
         | 
| 
       124 
133 
     | 
    
         
             
              msg = "#{ '3' * message_size }"
         
     | 
| 
       125 
134 
     | 
    
         | 
| 
       126 
135 
     | 
    
         
             
              start_time = Time.now
         
     | 
| 
       127 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
              msg = ""
         
     | 
| 
       128 
138 
     | 
    
         
             
              roundtrip_count.times do
         
     | 
| 
       129 
     | 
    
         
            -
                s.send_string msg, 0
         
     | 
| 
       130 
     | 
    
         
            -
                 
     | 
| 
      
 139 
     | 
    
         
            +
                rc = s.send_string msg, 0
         
     | 
| 
      
 140 
     | 
    
         
            +
                rc = s.recv_string msg
         
     | 
| 
       131 
141 
     | 
    
         
             
                raise "Message size doesn't match, expected [#{message_size}] but received [#{msg.size}]" if message_size != msg.size
         
     | 
| 
       132 
142 
     | 
    
         
             
              end
         
     | 
| 
       133 
143 
     | 
    
         | 
| 
         @@ -38,7 +38,7 @@ start_time = Time.now 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
            # kick it off
         
     | 
| 
       40 
40 
     | 
    
         
             
            message = ZMQ::Message.new("a" * message_size)
         
     | 
| 
       41 
     | 
    
         
            -
            assert(s1. 
     | 
| 
      
 41 
     | 
    
         
            +
            assert(s1.sendmsg(message, ZMQ::NonBlocking))
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
            i = roundtrip_count
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
         @@ -49,8 +49,8 @@ until i.zero? 
     | 
|
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
              poller.readables.each do |socket|
         
     | 
| 
       51 
51 
     | 
    
         
             
                received_message = ''
         
     | 
| 
       52 
     | 
    
         
            -
                assert(socket.recv_string(received_message, ZMQ:: 
     | 
| 
       53 
     | 
    
         
            -
                assert(socket. 
     | 
| 
      
 52 
     | 
    
         
            +
                assert(socket.recv_string(received_message, ZMQ::NonBlocking))
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert(socket.sendmsg(ZMQ::Message.new(received_message), ZMQ::NonBlocking))
         
     | 
| 
       54 
54 
     | 
    
         
             
              end
         
     | 
| 
       55 
55 
     | 
    
         
             
            end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
         @@ -28,13 +28,13 @@ assert(s.setsockopt(ZMQ::SUBSCRIBE, "")) 
     | 
|
| 
       28 
28 
     | 
    
         
             
            assert(s.bind(bind_to))
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
30 
     | 
    
         
             
            msg = ZMQ::Message.new
         
     | 
| 
       31 
     | 
    
         
            -
            assert(s. 
     | 
| 
      
 31 
     | 
    
         
            +
            assert(s.recvmsg(msg))
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
            start_time = Time.now
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
            i = 1
         
     | 
| 
       36 
36 
     | 
    
         
             
            while i < message_count
         
     | 
| 
       37 
     | 
    
         
            -
              assert(s. 
     | 
| 
      
 37 
     | 
    
         
            +
              assert(s.recvmsg(msg))
         
     | 
| 
       38 
38 
     | 
    
         
             
              i += 1
         
     | 
| 
       39 
39 
     | 
    
         
             
            end
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            if ARGV.length != 3
         
     | 
| 
      
 5 
     | 
    
         
            +
              puts "usage: ruby remote_throughput.rb <connect-to> <message-size> <message-count>"
         
     | 
| 
      
 6 
     | 
    
         
            +
              Process.exit
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            connect_to = ARGV[0]
         
     | 
| 
      
 10 
     | 
    
         
            +
            message_size = ARGV[1].to_i
         
     | 
| 
      
 11 
     | 
    
         
            +
            message_count = ARGV[2].to_i
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            def assert(rc)
         
     | 
| 
      
 14 
     | 
    
         
            +
              raise "Last API call failed at #{caller(1)}" unless rc >= 0
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            begin
         
     | 
| 
      
 18 
     | 
    
         
            +
              ctx = ZMQ::Context.new
         
     | 
| 
      
 19 
     | 
    
         
            +
              s = ZMQ::Socket.new(ctx.pointer, ZMQ::PUB)
         
     | 
| 
      
 20 
     | 
    
         
            +
            rescue ContextError => e
         
     | 
| 
      
 21 
     | 
    
         
            +
              STDERR.puts "Could not allocate a context or socket!"
         
     | 
| 
      
 22 
     | 
    
         
            +
              raise
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::LINGER, 1_000))
         
     | 
| 
      
 26 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::RCVHWM, 0))
         
     | 
| 
      
 27 
     | 
    
         
            +
            assert(s.setsockopt(ZMQ::HWM, 10))
         
     | 
| 
      
 28 
     | 
    
         
            +
            assert(s.bind(connect_to))
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            # the sleep gives the downstream SUB socket a chance to register its
         
     | 
| 
      
 31 
     | 
    
         
            +
            # subscription filters with this PUB socket
         
     | 
| 
      
 32 
     | 
    
         
            +
            puts "Hit any key to start publishing"
         
     | 
| 
      
 33 
     | 
    
         
            +
            STDIN.gets
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            i = 0
         
     | 
| 
      
 36 
     | 
    
         
            +
            while i < message_count
         
     | 
| 
      
 37 
     | 
    
         
            +
              msg = ZMQ::Message.new(i.to_s)
         
     | 
| 
      
 38 
     | 
    
         
            +
              assert(s.sendmsg(msg))
         
     | 
| 
      
 39 
     | 
    
         
            +
              puts i
         
     | 
| 
      
 40 
     | 
    
         
            +
              i += 1
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            sleep 10
         
     | 
| 
      
 44 
     | 
    
         
            +
            assert(s.close)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ctx.terminate
         
     | 
| 
         @@ -71,7 +71,7 @@ assert(s4.recv_string(body)) if s4.more_parts? 
     | 
|
| 
       71 
71 
     | 
    
         
             
            puts "s4 received topic [#{topic}], body [#{body}]"
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
73 
     | 
    
         
             
            s5_string = ''
         
     | 
| 
       74 
     | 
    
         
            -
            rc = s5.recv_string(s5_string, ZMQ:: 
     | 
| 
      
 74 
     | 
    
         
            +
            rc = s5.recv_string(s5_string, ZMQ::NonBlocking)
         
     | 
| 
       75 
75 
     | 
    
         
             
            eagain = (rc == -1 && ZMQ::Util.errno == ZMQ::EAGAIN)
         
     | 
| 
       76 
76 
     | 
    
         
             
            puts(eagain ? "s5 received no messages" : "s5 FAILED")
         
     | 
| 
       77 
77 
     | 
    
         | 
| 
         @@ -38,7 +38,7 @@ until @done do 
     | 
|
| 
       38 
38 
     | 
    
         
             
                payload = "#{ '3' * 1024 }"
         
     | 
| 
       39 
39 
     | 
    
         | 
| 
       40 
40 
     | 
    
         
             
                puts "sending payload nonblocking"
         
     | 
| 
       41 
     | 
    
         
            -
                assert(s1.send_string(payload, ZMQ:: 
     | 
| 
      
 41 
     | 
    
         
            +
                assert(s1.send_string(payload, ZMQ::NonBlocking))
         
     | 
| 
       42 
42 
     | 
    
         
             
                @unsent = false
         
     | 
| 
       43 
43 
     | 
    
         
             
              end
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
         @@ -46,7 +46,7 @@ until @done do 
     | 
|
| 
       46 
46 
     | 
    
         
             
              if Time.now - start_time > 1
         
     | 
| 
       47 
47 
     | 
    
         
             
                poller.readables.each do |sock|
         
     | 
| 
       48 
48 
     | 
    
         
             
                  received_msg = ''
         
     | 
| 
       49 
     | 
    
         
            -
                  assert(sock.recv_string(received_msg, ZMQ:: 
     | 
| 
      
 49 
     | 
    
         
            +
                  assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
51 
     | 
    
         
             
                  puts "message received [#{received_msg}]"
         
     | 
| 
       52 
52 
     | 
    
         
             
                  @done = true
         
     | 
| 
         @@ -27,8 +27,8 @@ payload = "#{ '3' * 2048 }" 
     | 
|
| 
       27 
27 
     | 
    
         
             
            sent_msg = ZMQ::Message.new(payload)
         
     | 
| 
       28 
28 
     | 
    
         
             
            received_msg = ZMQ::Message.new
         
     | 
| 
       29 
29 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
            assert(s1. 
     | 
| 
       31 
     | 
    
         
            -
            assert(s2. 
     | 
| 
      
 30 
     | 
    
         
            +
            assert(s1.sendmsg(sent_msg))
         
     | 
| 
      
 31 
     | 
    
         
            +
            assert(s2.recvmsg(received_msg))
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
            result = payload == received_msg.copy_out_string ? "Request received" : "Received wrong payload"
         
     | 
| 
       34 
34 
     | 
    
         | 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            #if ARGV.length != 3
         
     | 
| 
      
 5 
     | 
    
         
            +
            #  puts "usage: ruby local_throughtput.rb <bind-to> <message-size> <message-count>"
         
     | 
| 
      
 6 
     | 
    
         
            +
            #  Process.exit
         
     | 
| 
      
 7 
     | 
    
         
            +
            #end
         
     | 
| 
      
 8 
     | 
    
         
            +
            p ZMQ::Util.version
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            def assert(rc)
         
     | 
| 
      
 11 
     | 
    
         
            +
              raise "Last API call failed at #{caller(1)}" unless rc >= 0
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            bind_to = ARGV[0]
         
     | 
| 
      
 15 
     | 
    
         
            +
            message_size = ARGV[1].to_i
         
     | 
| 
      
 16 
     | 
    
         
            +
            message_count = ARGV[2].to_i
         
     | 
| 
      
 17 
     | 
    
         
            +
            sleep_time = ARGV[3].to_f
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            begin
         
     | 
| 
      
 20 
     | 
    
         
            +
              ctx = ZMQ::Context.new
         
     | 
| 
      
 21 
     | 
    
         
            +
              s = ZMQ::Socket.new(ctx.pointer, ZMQ::SUB)
         
     | 
| 
      
 22 
     | 
    
         
            +
            rescue ContextError => e
         
     | 
| 
      
 23 
     | 
    
         
            +
              STDERR.puts "Failed to allocate context or socket!"
         
     | 
| 
      
 24 
     | 
    
         
            +
              raise
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::LINGER, 100))
         
     | 
| 
      
 28 
     | 
    
         
            +
            assert(s.setsockopt(ZMQ::IDENTITY, rand(999_999).to_s))
         
     | 
| 
      
 29 
     | 
    
         
            +
            assert(s.setsockopt(ZMQ::SUBSCRIBE, ""))
         
     | 
| 
      
 30 
     | 
    
         
            +
            assert(s.setsockopt(ZMQ::HWM, 1))
         
     | 
| 
      
 31 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::RCVHWM, 0))
         
     | 
| 
      
 32 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::SNDHWM, 0))
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            assert(s.connect(bind_to))
         
     | 
| 
      
 35 
     | 
    
         
            +
            sleep 1
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            msg = ZMQ::Message.new
         
     | 
| 
      
 38 
     | 
    
         
            +
            msg = ''
         
     | 
| 
      
 39 
     | 
    
         
            +
            assert(s.recv_string(msg))
         
     | 
| 
      
 40 
     | 
    
         
            +
            raise unless msg.to_i == 0
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            start_time = Time.now
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            i = 1
         
     | 
| 
      
 45 
     | 
    
         
            +
            while i < message_count - 1
         
     | 
| 
      
 46 
     | 
    
         
            +
              assert(s.recv_string(msg))
         
     | 
| 
      
 47 
     | 
    
         
            +
              msg_i = msg.to_i
         
     | 
| 
      
 48 
     | 
    
         
            +
              missed = (msg_i - i) - 1
         
     | 
| 
      
 49 
     | 
    
         
            +
              puts "missed [#{missed}] messages" if missed > 0
         
     | 
| 
      
 50 
     | 
    
         
            +
              i = msg_i
         
     | 
| 
      
 51 
     | 
    
         
            +
              
         
     | 
| 
      
 52 
     | 
    
         
            +
              start = Time.now
         
     | 
| 
      
 53 
     | 
    
         
            +
              while (Time.now - start) < sleep_time
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            end_time = Time.now
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            elapsed = (end_time.to_f - start_time.to_f) * 1000000
         
     | 
| 
      
 60 
     | 
    
         
            +
            if elapsed == 0
         
     | 
| 
      
 61 
     | 
    
         
            +
              elapsed = 1
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            throughput = message_count * 1000000 / elapsed
         
     | 
| 
      
 65 
     | 
    
         
            +
            megabits = throughput * message_size * 8 / 1000000
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            puts "message size: %i [B]" % message_size
         
     | 
| 
      
 68 
     | 
    
         
            +
            puts "message count: %i" % message_count
         
     | 
| 
      
 69 
     | 
    
         
            +
            puts "mean throughput: %i [msg/s]" % throughput
         
     | 
| 
      
 70 
     | 
    
         
            +
            puts "mean throughput: %.3f [Mb/s]" % megabits
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            assert(s.close)
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            ctx.terminate
         
     | 
| 
         @@ -58,11 +58,11 @@ class Receiver 
     | 
|
| 
       58 
58 
     | 
    
         | 
| 
       59 
59 
     | 
    
         
             
              def run
         
     | 
| 
       60 
60 
     | 
    
         
             
                msg = ZMQ::Message.new
         
     | 
| 
       61 
     | 
    
         
            -
                assert(@socket. 
     | 
| 
      
 61 
     | 
    
         
            +
                assert(@socket.recvmsg(msg))
         
     | 
| 
       62 
62 
     | 
    
         | 
| 
       63 
63 
     | 
    
         
             
                elapsed = elapsed_microseconds do
         
     | 
| 
       64 
64 
     | 
    
         
             
                  (@count -1).times do
         
     | 
| 
       65 
     | 
    
         
            -
                    assert(@socket. 
     | 
| 
      
 65 
     | 
    
         
            +
                    assert(@socket.recvmsg(msg))
         
     | 
| 
       66 
66 
     | 
    
         
             
                  end
         
     | 
| 
       67 
67 
     | 
    
         
             
                end
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
         @@ -110,7 +110,7 @@ class Transmitter 
     | 
|
| 
       110 
110 
     | 
    
         
             
                i = 0
         
     | 
| 
       111 
111 
     | 
    
         
             
                while i < @count
         
     | 
| 
       112 
112 
     | 
    
         
             
                  msg = ZMQ::Message.new(contents)
         
     | 
| 
       113 
     | 
    
         
            -
                  assert(@socket. 
     | 
| 
      
 113 
     | 
    
         
            +
                  assert(@socket.sendmsg(msg))
         
     | 
| 
       114 
114 
     | 
    
         
             
                  i += 1
         
     | 
| 
       115 
115 
     | 
    
         
             
                end
         
     | 
| 
       116 
116 
     | 
    
         | 
| 
         @@ -43,7 +43,7 @@ until @done do 
     | 
|
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
                5.times do |i|
         
     | 
| 
       45 
45 
     | 
    
         
             
                  payload = "#{ i.to_s * 40 }"
         
     | 
| 
       46 
     | 
    
         
            -
                  assert(s1.send_string(payload, ZMQ:: 
     | 
| 
      
 46 
     | 
    
         
            +
                  assert(s1.send_string(payload, ZMQ::NonBlocking))
         
     | 
| 
       47 
47 
     | 
    
         
             
                end
         
     | 
| 
       48 
48 
     | 
    
         
             
                @unsent = false
         
     | 
| 
       49 
49 
     | 
    
         
             
              end
         
     | 
| 
         @@ -54,12 +54,12 @@ until @done do 
     | 
|
| 
       54 
54 
     | 
    
         | 
| 
       55 
55 
     | 
    
         
             
                  if sock.identity =~ /xrep/
         
     | 
| 
       56 
56 
     | 
    
         
             
                    routing_info = ''
         
     | 
| 
       57 
     | 
    
         
            -
                    assert(sock.recv_string(routing_info, ZMQ:: 
     | 
| 
      
 57 
     | 
    
         
            +
                    assert(sock.recv_string(routing_info, ZMQ::NonBlocking))
         
     | 
| 
       58 
58 
     | 
    
         
             
                    puts "routing_info received [#{routing_info}] on socket.identity [#{sock.identity}]"
         
     | 
| 
       59 
59 
     | 
    
         
             
                  else
         
     | 
| 
       60 
60 
     | 
    
         
             
                    routing_info = nil
         
     | 
| 
       61 
61 
     | 
    
         
             
                    received_msg = ''
         
     | 
| 
       62 
     | 
    
         
            -
                    assert(sock.recv_string(received_msg, ZMQ:: 
     | 
| 
      
 62 
     | 
    
         
            +
                    assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
         
     | 
| 
       63 
63 
     | 
    
         | 
| 
       64 
64 
     | 
    
         
             
                    # skip to the next iteration if received_msg is nil; that means we got an EAGAIN
         
     | 
| 
       65 
65 
     | 
    
         
             
                    next unless received_msg
         
     | 
| 
         @@ -68,13 +68,13 @@ until @done do 
     | 
|
| 
       68 
68 
     | 
    
         | 
| 
       69 
69 
     | 
    
         
             
                  while sock.more_parts? do
         
     | 
| 
       70 
70 
     | 
    
         
             
                    received_msg = ''
         
     | 
| 
       71 
     | 
    
         
            -
                    assert(sock.recv_string(received_msg, ZMQ:: 
     | 
| 
      
 71 
     | 
    
         
            +
                    assert(sock.recv_string(received_msg, ZMQ::NonBlocking))
         
     | 
| 
       72 
72 
     | 
    
         | 
| 
       73 
73 
     | 
    
         
             
                    puts "message received [#{received_msg}]"
         
     | 
| 
       74 
74 
     | 
    
         
             
                  end
         
     | 
| 
       75 
75 
     | 
    
         | 
| 
       76 
76 
     | 
    
         
             
                  puts "kick back a reply"
         
     | 
| 
       77 
     | 
    
         
            -
                  assert(sock.send_string(routing_info, ZMQ::SNDMORE | ZMQ:: 
     | 
| 
      
 77 
     | 
    
         
            +
                  assert(sock.send_string(routing_info, ZMQ::SNDMORE | ZMQ::NonBlocking)) if routing_info
         
     | 
| 
       78 
78 
     | 
    
         
             
                  time = Time.now.strftime "%Y-%m-%dT%H:%M:%S.#{Time.now.usec}"
         
     | 
| 
       79 
79 
     | 
    
         
             
                  reply = "reply " + sock.identity.upcase + " #{time}"
         
     | 
| 
       80 
80 
     | 
    
         
             
                  puts "sent reply [#{reply}], #{time}"
         
     | 
| 
         @@ -38,7 +38,7 @@ start_time = Time.now 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
            # kick it off
         
     | 
| 
       40 
40 
     | 
    
         
             
            message = ZMQ::Message.new("a" * message_size)
         
     | 
| 
       41 
     | 
    
         
            -
            assert(s1.sendmsg(message, ZMQ:: 
     | 
| 
      
 41 
     | 
    
         
            +
            assert(s1.sendmsg(message, ZMQ::NonBlocking))
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
            i = roundtrip_count
         
     | 
| 
       44 
44 
     | 
    
         | 
| 
         @@ -49,8 +49,8 @@ until i.zero? 
     | 
|
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
              poller.readables.each do |socket|
         
     | 
| 
       51 
51 
     | 
    
         
             
                received_message = ''
         
     | 
| 
       52 
     | 
    
         
            -
                assert(socket.recv_string(received_message, ZMQ:: 
     | 
| 
       53 
     | 
    
         
            -
                assert(socket.sendmsg(ZMQ::Message.new(received_message), ZMQ:: 
     | 
| 
      
 52 
     | 
    
         
            +
                assert(socket.recv_string(received_message, ZMQ::NonBlocking))
         
     | 
| 
      
 53 
     | 
    
         
            +
                assert(socket.sendmsg(ZMQ::Message.new(received_message), ZMQ::NonBlocking))
         
     | 
| 
       54 
54 
     | 
    
         
             
              end
         
     | 
| 
       55 
55 
     | 
    
         
             
            end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
             
     | 
| 
      
 2 
     | 
    
         
            +
            require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'ffi-rzmq')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            if ARGV.length != 3
         
     | 
| 
      
 5 
     | 
    
         
            +
              puts "usage: ruby remote_throughput.rb <connect-to> <message-size> <message-count>"
         
     | 
| 
      
 6 
     | 
    
         
            +
              Process.exit
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            connect_to = ARGV[0]
         
     | 
| 
      
 10 
     | 
    
         
            +
            message_size = ARGV[1].to_i
         
     | 
| 
      
 11 
     | 
    
         
            +
            message_count = ARGV[2].to_i
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            def assert(rc)
         
     | 
| 
      
 14 
     | 
    
         
            +
              raise "Last API call failed at #{caller(1)}" unless rc >= 0
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            begin
         
     | 
| 
      
 18 
     | 
    
         
            +
              ctx = ZMQ::Context.new
         
     | 
| 
      
 19 
     | 
    
         
            +
              s = ZMQ::Socket.new(ctx.pointer, ZMQ::PUB)
         
     | 
| 
      
 20 
     | 
    
         
            +
            rescue ContextError => e
         
     | 
| 
      
 21 
     | 
    
         
            +
              STDERR.puts "Could not allocate a context or socket!"
         
     | 
| 
      
 22 
     | 
    
         
            +
              raise
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::LINGER, 1_000))
         
     | 
| 
      
 26 
     | 
    
         
            +
            #assert(s.setsockopt(ZMQ::RCVHWM, 0))
         
     | 
| 
      
 27 
     | 
    
         
            +
            assert(s.setsockopt(ZMQ::SNDHWM, 100))
         
     | 
| 
      
 28 
     | 
    
         
            +
            assert(s.bind(connect_to))
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            # the sleep gives the downstream SUB socket a chance to register its
         
     | 
| 
      
 31 
     | 
    
         
            +
            # subscription filters with this PUB socket
         
     | 
| 
      
 32 
     | 
    
         
            +
            puts "Hit any key to start publishing"
         
     | 
| 
      
 33 
     | 
    
         
            +
            STDIN.gets
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            i = 0
         
     | 
| 
      
 36 
     | 
    
         
            +
            while i < message_count
         
     | 
| 
      
 37 
     | 
    
         
            +
              msg = ZMQ::Message.new(i.to_s)
         
     | 
| 
      
 38 
     | 
    
         
            +
              assert(s.sendmsg(msg))
         
     | 
| 
      
 39 
     | 
    
         
            +
              puts i
         
     | 
| 
      
 40 
     | 
    
         
            +
              i += 1
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            sleep 10
         
     | 
| 
      
 44 
     | 
    
         
            +
            assert(s.close)
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ctx.terminate
         
     |