ffi-rzmq 0.9.2 → 0.9.3

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.
@@ -1,3 +1,21 @@
1
+ == 0.9.3 / 20111214
2
+ * Performance optimizations for #getsockopt.
3
+
4
+ * Fixed Message#copy and Message#move. They didn't work before.
5
+
6
+ * Cache LibZM::Msg.size in the ZMQ::Message class so that
7
+ initialization can skip recalculating what is effectively a
8
+ constant value. This speeds up ZMQ::Message instantiation by
9
+ 5 to 10%. Wow.
10
+
11
+ * Modified calls to #super to use explicit arguments (e.g. #super())
12
+ because otherwise the Ruby runtime has to (at runtime) dig out
13
+ the arguments that are expected to be passed up the chain. By
14
+ explicitly listing the args and using parentheses, the runtime
15
+ can avoid that work and dispatch directly. This effects all
16
+ Ruby runtimes, but it was through the work of Evan Phoenix that
17
+ I figured this out. Results in a 2-5% speedup on method dispatch.
18
+
1
19
  == 0.9.2 / 20111115
2
20
  * Removed all references to the version4 API.
3
21
 
@@ -21,7 +21,7 @@ MRI 1.9.x, Rubinius and JRuby.}
21
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
22
  s.require_paths = ["lib"]
23
23
 
24
- s.add_runtime_dependency "ffi", [">= 1.0.9"]
24
+ s.add_runtime_dependency "ffi"#, [">= 1.0.9"]
25
25
  s.add_development_dependency "rspec", ["~> 2.6"]
26
26
  s.add_development_dependency "rake"
27
27
  end
@@ -94,12 +94,10 @@ module ZMQ
94
94
  end
95
95
 
96
96
  def initialize message = nil
97
- @state = :uninitialized
98
-
99
97
  # allocate our own pointer so that we can tell it to *not* zero out
100
98
  # the memory; it's pointless work since the library is going to
101
99
  # overwrite it anyway.
102
- @pointer = FFI::MemoryPointer.new LibZMQ::Msg.size, 1, false
100
+ @pointer = FFI::MemoryPointer.new Message.msg_size, 1, false
103
101
 
104
102
  if message
105
103
  copy_in_string message
@@ -147,11 +145,11 @@ module ZMQ
147
145
  alias :pointer :address
148
146
 
149
147
  def copy source
150
- LibZMQ.zmq_msg_copy @pointer, source.address
148
+ LibZMQ.zmq_msg_copy @pointer, source
151
149
  end
152
150
 
153
151
  def move source
154
- LibZMQ.zmq_msg_move @pointer, source.address
152
+ LibZMQ.zmq_msg_move @pointer, source
155
153
  end
156
154
 
157
155
  # Provides the size of the data buffer for this +zmq_msg_t+ C struct.
@@ -193,6 +191,12 @@ module ZMQ
193
191
 
194
192
  rc
195
193
  end
194
+
195
+ # cache the msg size so we don't have to recalculate it when creating
196
+ # each new instance
197
+ @msg_size = LibZMQ::Msg.size
198
+
199
+ def self.msg_size() @msg_size; end
196
200
 
197
201
  end # class Message
198
202
 
@@ -228,7 +232,7 @@ module ZMQ
228
232
  # handles deallocation of the native memory buffer.
229
233
  #
230
234
  def copy_in_bytes bytes, len
231
- rc = super
235
+ rc = super(bytes, len)
232
236
 
233
237
  # make sure we have a way to deallocate this memory if the object goes
234
238
  # out of scope
@@ -240,7 +244,7 @@ module ZMQ
240
244
  # buffer.
241
245
  #
242
246
  def close
243
- rc = super
247
+ rc = super()
244
248
  remove_finalizer
245
249
  rc
246
250
  end
@@ -268,6 +272,11 @@ module ZMQ
268
272
  end
269
273
  end
270
274
 
275
+ # cache the msg size so we don't have to recalculate it when creating
276
+ # each new instance
277
+ # need to do this again because ivars are not inheritable
278
+ @msg_size = LibZMQ::Msg.size
279
+
271
280
  end # class ManagedMessage
272
281
 
273
282
  end # module ZMQ
@@ -82,7 +82,9 @@ module ZMQ
82
82
  raise ContextError.new 'zmq_socket', 0, ETERM, "Context pointer was null"
83
83
  end
84
84
 
85
- @sockopt_cache = {}
85
+ @more_parts_array = []
86
+ @option_lookup = []
87
+ populate_option_lookup
86
88
 
87
89
  define_finalizer
88
90
  end
@@ -123,17 +125,17 @@ module ZMQ
123
125
  # ZMQ::Util.resultcode_ok?(rc) ? puts("succeeded") : puts("failed")
124
126
  #
125
127
  def setsockopt name, value, length = nil
126
- if long_long_option?(name)
128
+ if 1 == @option_lookup[name]
127
129
  length = 8
128
130
  pointer = LibC.malloc length
129
131
  pointer.write_long_long value
130
132
 
131
- elsif int_option?(name)
133
+ elsif 0 == @option_lookup[name]
132
134
  length = 4
133
135
  pointer = LibC.malloc length
134
136
  pointer.write_int value
135
137
 
136
- elsif string_option?(name)
138
+ elsif 2 == @option_lookup[name]
137
139
  length ||= value.size
138
140
 
139
141
  # note: not checking errno for failed memory allocations :(
@@ -166,10 +168,9 @@ module ZMQ
166
168
  # end
167
169
  #
168
170
  def more_parts?
169
- array = []
170
- rc = getsockopt ZMQ::RCVMORE, array
171
+ rc = getsockopt ZMQ::RCVMORE, @more_parts_array
171
172
 
172
- Util.resultcode_ok?(rc) ? array.at(0) : false
173
+ Util.resultcode_ok?(rc) ? @more_parts_array.at(0) : false
173
174
  end
174
175
 
175
176
  # Binds the socket to an +address+.
@@ -213,20 +214,22 @@ module ZMQ
213
214
  private
214
215
 
215
216
  def __getsockopt__ name, array
216
- value, length = sockopt_buffers name
217
+ # a small optimization so we only have to determine the option
218
+ # type a single time; gives approx 5% speedup to do it this way.
219
+ option_type = @option_lookup[name]
220
+
221
+ value, length = sockopt_buffers option_type
217
222
 
218
223
  rc = LibZMQ.zmq_getsockopt @socket, name, value, length
219
224
 
220
225
  if Util.resultcode_ok?(rc)
221
- result = if int_option?(name)
222
- value.read_int
223
- elsif long_long_option?(name)
226
+ array[0] = if 1 == option_type
224
227
  value.read_long_long
225
- elsif string_option?(name)
228
+ elsif 0 == option_type
229
+ value.read_int
230
+ elsif 2 == option_type
226
231
  value.read_string(length.read_int)
227
232
  end
228
-
229
- array << result
230
233
  end
231
234
 
232
235
  rc
@@ -235,28 +238,28 @@ module ZMQ
235
238
  # Calls to ZMQ.getsockopt require us to pass in some pointers. We can cache and save those buffers
236
239
  # for subsequent calls. This is a big perf win for calling RCVMORE which happens quite often.
237
240
  # Cannot save the buffer for the IDENTITY.
238
- def sockopt_buffers name
239
- if long_long_option?(name)
241
+ def sockopt_buffers option_type
242
+ if 1 == option_type
240
243
  # int64_t or uint64_t
241
- unless @sockopt_cache[:int64]
244
+ unless @longlong_cache
242
245
  length = FFI::MemoryPointer.new :size_t
243
246
  length.write_int 8
244
- @sockopt_cache[:int64] = [FFI::MemoryPointer.new(:int64), length]
247
+ @longlong_cache = [FFI::MemoryPointer.new(:int64), length]
245
248
  end
246
249
 
247
- @sockopt_cache[:int64]
250
+ @longlong_cache
248
251
 
249
- elsif int_option?(name)
252
+ elsif 0 == option_type
250
253
  # int, 0mq assumes int is 4-bytes
251
- unless @sockopt_cache[:int32]
254
+ unless @int_cache
252
255
  length = FFI::MemoryPointer.new :size_t
253
256
  length.write_int 4
254
- @sockopt_cache[:int32] = [FFI::MemoryPointer.new(:int32), length]
257
+ @int_cache = [FFI::MemoryPointer.new(:int32), length]
255
258
  end
256
259
 
257
- @sockopt_cache[:int32]
260
+ @int_cache
258
261
 
259
- elsif string_option?(name)
262
+ elsif 2 == option_type
260
263
  length = FFI::MemoryPointer.new :size_t
261
264
  # could be a string of up to 255 bytes
262
265
  length.write_int 255
@@ -264,50 +267,30 @@ module ZMQ
264
267
 
265
268
  else
266
269
  # uh oh, someone passed in an unknown option; use a slop buffer
267
- unless @sockopt_cache[:unknown]
270
+ unless @int_cache
268
271
  length = FFI::MemoryPointer.new :size_t
269
272
  length.write_int 4
270
- @sockopt_cache[:unknown] = [FFI::MemoryPointer.new(:int32), length]
273
+ @int_cache = [FFI::MemoryPointer.new(:int32), length]
271
274
  end
272
275
 
273
- @sockopt_cache[:unknown]
276
+ @int_cache
274
277
  end
275
278
  end
276
-
277
- def supported_option? name
278
- int_option?(name) || long_long_option?(name) || string_option?(name)
279
- end
280
-
281
- def int_option? name
282
- EVENTS == name ||
283
- LINGER == name ||
284
- RECONNECT_IVL == name ||
285
- FD == name ||
286
- TYPE == name ||
287
- BACKLOG == name
288
- end
289
-
290
- def string_option? name
291
- SUBSCRIBE == name ||
292
- UNSUBSCRIBE == name
293
- end
294
-
295
- def long_long_option? name
296
- RCVMORE == name ||
297
- AFFINITY == name
298
- end
299
-
300
- def unsupported_setsock_option? name
301
- RCVMORE == name
302
- end
303
-
304
- def unsupported_getsock_option? name
305
- UNSUBSCRIBE == name ||
306
- SUBSCRIBE == name
279
+
280
+ def populate_option_lookup
281
+ # integer options
282
+ [EVENTS, LINGER, RECONNECT_IVL, FD, TYPE, BACKLOG].each { |option| @option_lookup[option] = 0 }
283
+
284
+ # long long options
285
+ [RCVMORE, AFFINITY].each { |option| @option_lookup[option] = 1 }
286
+
287
+ # string options
288
+ [SUBSCRIBE, UNSUBSCRIBE].each { |option| @option_lookup[option] = 2 }
307
289
  end
308
290
 
309
291
  def release_cache
310
- @sockopt_cache.clear
292
+ @longlong_cache = nil
293
+ @int_cache = nil
311
294
  end
312
295
  end # module CommonSocketBehavior
313
296
 
@@ -330,11 +313,14 @@ module ZMQ
330
313
 
331
314
 
332
315
  private
333
-
334
- def string_option? name
335
- super ||
336
- IDENTITY == name
316
+
317
+ def populate_option_lookup
318
+ super()
319
+
320
+ # string options
321
+ [IDENTITY].each { |option| @option_lookup[option] = 2 }
337
322
  end
323
+
338
324
  end # module IdentitySupport
339
325
 
340
326
 
@@ -658,23 +644,16 @@ module ZMQ
658
644
  def noblock? flags
659
645
  (NOBLOCK & flags) == NOBLOCK
660
646
  end
647
+
648
+ def populate_option_lookup
649
+ super()
650
+
651
+ # integer options
652
+ [RECONNECT_IVL_MAX].each { |option| @option_lookup[option] = 0 }
661
653
 
662
- def int_option? name
663
- super ||
664
- RECONNECT_IVL_MAX == name
665
- end
666
-
667
- def long_long_option? name
668
- super ||
669
- HWM == name ||
670
- SWAP == name ||
671
- RATE == name ||
672
- RECOVERY_IVL == name ||
673
- RECOVERY_IVL_MSEC == name ||
674
- MCAST_LOOP == name ||
675
- SNDBUF == name ||
676
- RCVBUF == name
677
- end
654
+ # long long options
655
+ [HWM, SWAP, RATE, RECOVERY_IVL, RECOVERY_IVL_MSEC, MCAST_LOOP, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 1 }
656
+ end
678
657
 
679
658
  # these finalizer-related methods cannot live in the CommonSocketBehavior
680
659
  # module; they *must* be in the class definition directly
@@ -986,7 +965,7 @@ module ZMQ
986
965
  alias :noblock? :dontwait?
987
966
 
988
967
  def int_option? name
989
- super ||
968
+ super(name) ||
990
969
  RECONNECT_IVL_MAX == name ||
991
970
  RCVHWM == name ||
992
971
  SNDHWM == name ||
@@ -995,6 +974,13 @@ module ZMQ
995
974
  SNDBUF == name ||
996
975
  RCVBUF == name
997
976
  end
977
+
978
+ def populate_option_lookup
979
+ super()
980
+
981
+ # integer options
982
+ [RECONNECT_IVL_MAX, RCVHWM, SNDHWM, RATE, RECOVERY_IVL, SNDBUF, RCVBUF].each { |option| @option_lookup[option] = 0 }
983
+ end
998
984
 
999
985
  # these finalizer-related methods cannot live in the CommonSocketBehavior
1000
986
  # module; they *must* be in the class definition directly
@@ -1,3 +1,3 @@
1
1
  module ZMQ
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.3"
3
3
  end
@@ -366,12 +366,22 @@ module ZMQ
366
366
  array[0].should == value
367
367
  end
368
368
 
369
- it "should default to a value of -1" do
370
- value = -1
371
- array = []
372
- rc = socket.getsockopt(ZMQ::LINGER, array)
373
- rc.should == 0
374
- array[0].should == value
369
+ if ZMQ::SUB == socket_type || ZMQ::XSUB == socket_type
370
+ it "should default to a value of 0" do
371
+ value = 0
372
+ array = []
373
+ rc = socket.getsockopt(ZMQ::LINGER, array)
374
+ rc.should == 0
375
+ array[0].should == value
376
+ end
377
+ else
378
+ it "should default to a value of -1" do
379
+ value = -1
380
+ array = []
381
+ rc = socket.getsockopt(ZMQ::LINGER, array)
382
+ rc.should == 0
383
+ array[0].should == value
384
+ end
375
385
  end
376
386
  end # context using option ZMQ::LINGER
377
387
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ffi-rzmq
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.9.2
5
+ version: 0.9.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Chuck Remes
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-11-30 00:00:00 -06:00
14
- default_executable:
13
+ date: 2011-12-20 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: ffi
@@ -21,7 +20,7 @@ dependencies:
21
20
  requirements:
22
21
  - - ">="
23
22
  - !ruby/object:Gem::Version
24
- version: 1.0.9
23
+ version: "0"
25
24
  type: :runtime
26
25
  version_requirements: *id001
27
26
  - !ruby/object:Gem::Dependency
@@ -115,7 +114,6 @@ files:
115
114
  - spec/reqrep_spec.rb
116
115
  - spec/socket_spec.rb
117
116
  - spec/spec_helper.rb
118
- has_rdoc: true
119
117
  homepage: http://github.com/chuckremes/ffi-rzmq
120
118
  licenses: []
121
119
 
@@ -139,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
137
  requirements: []
140
138
 
141
139
  rubyforge_project: ffi-rzmq
142
- rubygems_version: 1.5.1
140
+ rubygems_version: 1.8.9
143
141
  signing_key:
144
142
  specification_version: 3
145
143
  summary: This gem wraps the ZeroMQ (0mq) networking library using Ruby FFI (foreign function interface).