memcached 0.14 → 0.15

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.
@@ -26,9 +26,9 @@ class Memcached
26
26
  DIRECT_VALUE_BEHAVIORS = [:retry_timeout, :connect_timeout, :rcv_timeout, :socket_recv_size, :poll_timeout, :socket_send_size, :server_failure_limit]
27
27
 
28
28
  CONVERSION_FACTORS = {
29
- :connect_timeout => 1_000_000,
30
29
  :rcv_timeout => 1_000_000,
31
- :poll_timeout => 1_000
30
+ :poll_timeout => 1_000,
31
+ :connect_timeout => 1_000
32
32
  }
33
33
 
34
34
  #:startdoc:
@@ -34,6 +34,7 @@ Subclasses correspond one-to-one with server response strings or libmemcached er
34
34
  * Memcached::ServerDelete
35
35
  * Memcached::ServerEnd
36
36
  * Memcached::ServerError
37
+ * Memcached::ServerIsMarkedDead
37
38
  * Memcached::ServerValue
38
39
  * Memcached::SomeErrorsWereReported
39
40
  * Memcached::StatValue
@@ -54,13 +55,15 @@ Subclasses correspond one-to-one with server response strings or libmemcached er
54
55
  end
55
56
  end
56
57
 
58
+ ERRNO_HASH = Hash[*Errno.constants.map{ |c| [Errno.const_get(c)::Errno, Errno.const_get(c).new.message] }.flatten]
59
+
57
60
  EXCEPTIONS = []
58
61
  EMPTY_STRUCT = Rlibmemcached::MemcachedSt.new
59
62
  Rlibmemcached.memcached_create(EMPTY_STRUCT)
60
63
 
61
64
  # Generate exception classes
62
65
  Rlibmemcached::MEMCACHED_MAXIMUM_RETURN.times do |index|
63
- description = Rlibmemcached.memcached_strerror(EMPTY_STRUCT, index)
66
+ description = Rlibmemcached.memcached_strerror(EMPTY_STRUCT, index).gsub("!", "")
64
67
  exception_class = eval("class #{camelize(description)} < Error; self; end")
65
68
  EXCEPTIONS << exception_class
66
69
  end
@@ -77,8 +80,5 @@ Subclasses correspond one-to-one with server response strings or libmemcached er
77
80
  end
78
81
  end
79
82
 
80
- # Verify library version
81
- # XXX Waiting on libmemcached 0.18
82
-
83
83
  #:startdoc:
84
84
  end
@@ -7,7 +7,7 @@ class Memcached
7
7
  FLAGS = 0x0
8
8
 
9
9
  DEFAULTS = {
10
- :hash => :default,
10
+ :hash => :fnv1_32,
11
11
  :no_block => false,
12
12
  :distribution => :consistent_ketama,
13
13
  :ketama_weighted => true,
@@ -26,9 +26,10 @@ class Memcached
26
26
  :default_ttl => 604800,
27
27
  :default_weight => 8,
28
28
  :sort_hosts => false,
29
- :auto_eject_hosts => false,
29
+ :auto_eject_hosts => true,
30
30
  :server_failure_limit => 2,
31
- :verify_key => true
31
+ :verify_key => true,
32
+ :use_udp => false
32
33
  }
33
34
 
34
35
  #:stopdoc:
@@ -51,11 +52,11 @@ Weights only affect Ketama hashing. If you use Ketama hashing and don't specify
51
52
  Valid option parameters are:
52
53
 
53
54
  <tt>:prefix_key</tt>:: A string to prepend to every key, for namespacing. Max length is 127.
54
- <tt>:hash</tt>:: The name of a hash function to use. Possible values are: <tt>:crc</tt>, <tt>:default</tt>, <tt>:fnv1_32</tt>, <tt>:fnv1_64</tt>, <tt>:fnv1a_32</tt>, <tt>:fnv1a_64</tt>, <tt>:hsieh</tt>, <tt>:md5</tt>, and <tt>:murmur</tt>. <tt>:default</tt> is the fastest. Use <tt>:md5</tt> for compatibility with other ketama clients.
55
+ <tt>:hash</tt>:: The name of a hash function to use. Possible values are: <tt>:crc</tt>, <tt>:default</tt>, <tt>:fnv1_32</tt>, <tt>:fnv1_64</tt>, <tt>:fnv1a_32</tt>, <tt>:fnv1a_64</tt>, <tt>:hsieh</tt>, <tt>:md5</tt>, and <tt>:murmur</tt>. <tt>:fnv1_32</tt> is fast and well known, and is the default. Use <tt>:md5</tt> for compatibility with other ketama clients.
55
56
  <tt>:distribution</tt>:: Either <tt>:modula</tt>, <tt>:consistent_ketama</tt>, <tt>:consistent_wheel</tt>, or <tt>:ketama</tt>. Defaults to <tt>:ketama</tt>.
56
57
  <tt>:server_failure_limit</tt>:: How many consecutive failures to allow before marking a host as dead. Has no effect unless <tt>:retry_timeout</tt> is also set.
57
58
  <tt>:retry_timeout</tt>:: How long to wait until retrying a dead server. Has no effect unless <tt>:server_failure_limit</tt> is non-zero. Defaults to <tt>30</tt>.
58
- <tt>:auto_eject_hosts</tt>:: Whether to temporarily eject dead hosts from the pool. Defaults to <tt>false</tt>. Note that in the event of an ejection, <tt>:auto_eject_hosts</tt> will remap the entire pool unless <tt>:distribution</tt> is set to <tt>:consistent</tt>.
59
+ <tt>:auto_eject_hosts</tt>:: Whether to temporarily eject dead hosts from the pool. Defaults to <tt>true</tt>. Note that in the event of an ejection, <tt>:auto_eject_hosts</tt> will remap the entire pool unless <tt>:distribution</tt> is set to <tt>:consistent</tt>.
59
60
  <tt>:cache_lookups</tt>:: Whether to cache hostname lookups for the life of the instance. Defaults to <tt>true</tt>.
60
61
  <tt>:support_cas</tt>:: Flag CAS support in the client. Accepts <tt>true</tt> or <tt>false</tt>. Defaults to <tt>false</tt> because it imposes a slight performance penalty. Note that your server must also support CAS or you will trigger <b>Memcached::ProtocolError</b> exceptions.
61
62
  <tt>:tcp_nodelay</tt>:: Turns on the no-delay feature for connecting sockets. Accepts <tt>true</tt> or <tt>false</tt>. Performance may or may not change, depending on your system.
@@ -64,10 +65,10 @@ Valid option parameters are:
64
65
  <tt>:show_backtraces</tt>:: Whether <b>Memcached::NotFound</b> exceptions should include backtraces. Generating backtraces is slow, so this is off by default. Turn it on to ease debugging.
65
66
  <tt>:connect_timeout</tt>:: How long to wait for a connection to a server. Defaults to 2 seconds. Set to <tt>0</tt> if you want to wait forever.
66
67
  <tt>:timeout</tt>:: How long to wait for a response from the server. Defaults to 0.25 seconds. Set to <tt>0</tt> if you want to wait forever.
67
- <tt>:poll_timeout</tt>:: How long to wait for a response from the server in the non-blocking select loop. Defaults to 0.25 seconds. Set to <tt>0</tt> if you want to wait forever.
68
68
  <tt>:default_ttl</tt>:: The <tt>ttl</tt> to use on set if no <tt>ttl</tt> is specified, in seconds. Defaults to one week. Set to <tt>0</tt> if you want things to never expire.
69
69
  <tt>:default_weight</tt>:: The weight to use if <tt>:ketama_weighted</tt> is <tt>true</tt>, but no weight is specified for a server.
70
70
  <tt>:hash_with_prefix_key</tt>:: Whether to include the prefix when calculating which server a key falls on. Defaults to <tt>true</tt>.
71
+ <tt>:use_udp</tt>:: Use the UDP protocol to reduce connection overhead. Defaults to false.
71
72
  <tt>:sort_hosts</tt>:: Whether to force the server list to stay sorted. This defeats consistent hashing and is rarely useful.
72
73
  <tt>:verify_key</tt>:: Validate keys before accepting them. Never disable this.
73
74
 
@@ -80,9 +81,9 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
80
81
  Lib.memcached_create(@struct)
81
82
 
82
83
  # Merge option defaults and discard meaningless keys
83
- @options = Hash[*DEFAULTS.map do |key, default|
84
- [key, opts[key] || default]
85
- end.flatten]
84
+ @options = DEFAULTS.merge(opts)
85
+ @options.delete_if { |k,v| not DEFAULTS.keys.include? k }
86
+ @default_ttl = options[:default_ttl]
86
87
 
87
88
  # Force :buffer_requests to use :no_block
88
89
  # XXX Deleting the :no_block key should also work, but libmemcached doesn't seem to set it
@@ -186,19 +187,19 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
186
187
  #
187
188
  # Also accepts a <tt>marshal</tt> value, which defaults to <tt>true</tt>. Set <tt>marshal</tt> to <tt>false</tt> if you want the <tt>value</tt> to be set directly.
188
189
  #
189
- def set(key, value, ttl=nil, marshal=true, flags=FLAGS)
190
+ def set(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
190
191
  value = marshal ? Marshal.dump(value) : value.to_s
191
192
  check_return_code(
192
- Lib.memcached_set(@struct, key, value, ttl || options[:default_ttl], flags),
193
+ Lib.memcached_set(@struct, key, value, ttl, flags),
193
194
  key
194
195
  )
195
196
  end
196
197
 
197
198
  # Add a key/value pair. Raises <b>Memcached::NotStored</b> if the key already exists on the server. The parameters are the same as <tt>set</tt>.
198
- def add(key, value, ttl=nil, marshal=true, flags=FLAGS)
199
+ def add(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
199
200
  value = marshal ? Marshal.dump(value) : value.to_s
200
201
  check_return_code(
201
- Lib.memcached_add(@struct, key, value, ttl || options[:default_ttl], flags),
202
+ Lib.memcached_add(@struct, key, value, ttl, flags),
202
203
  key
203
204
  )
204
205
  end
@@ -227,10 +228,10 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
227
228
  #:startdoc:
228
229
 
229
230
  # Replace a key/value pair. Raises <b>Memcached::NotFound</b> if the key does not exist on the server. The parameters are the same as <tt>set</tt>.
230
- def replace(key, value, ttl=nil, marshal=true, flags=FLAGS)
231
+ def replace(key, value, ttl=@default_ttl, marshal=true, flags=FLAGS)
231
232
  value = marshal ? Marshal.dump(value) : value.to_s
232
233
  check_return_code(
233
- Lib.memcached_replace(@struct, key, value, ttl || options[:default_ttl], flags),
234
+ Lib.memcached_replace(@struct, key, value, ttl, flags),
234
235
  key
235
236
  )
236
237
  end
@@ -261,19 +262,22 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
261
262
  #
262
263
  # CAS stands for "compare and swap", and avoids the need for manual key mutexing. CAS support must be enabled in Memcached.new or a <b>Memcached::ClientError</b> will be raised. Note that CAS may be buggy in memcached itself.
263
264
  #
264
- def cas(key, ttl=nil, marshal=true, flags=FLAGS)
265
+ def cas(key, ttl=@default_ttl, marshal=true, flags=FLAGS)
265
266
  raise ClientError, "CAS not enabled for this Memcached instance" unless options[:support_cas]
266
267
 
267
- value = get(key, marshal)
268
+ value, flags, ret = Lib.memcached_get_rvalue(@struct, key)
269
+ check_return_code(ret, key)
270
+ cas = @struct.result.cas
271
+
272
+ value = Marshal.load(value) if marshal
268
273
  value = yield value
269
- value = marshal ? Marshal.dump(value) : value.to_s
274
+ value = Marshal.dump(value) if marshal
270
275
 
271
- check_return_code(
272
- Lib.memcached_cas(@struct, key, value, ttl || options[:default_ttl], flags, @struct.result.cas),
273
- key
274
- )
276
+ check_return_code(Lib.memcached_cas(@struct, key, value, ttl, flags, cas), key)
275
277
  end
276
278
 
279
+ alias :compare_and_swap :cas
280
+
277
281
  ### Deleters
278
282
 
279
283
  # Deletes a key/value pair from the server. Accepts a String <tt>key</tt>. Raises <b>Memcached::NotFound</b> if the key does not exist.
@@ -332,7 +336,7 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
332
336
 
333
337
  # Return the server used by a particular key.
334
338
  def server_by_key(key)
335
- ret = Lib.memcached_server_by_key(@struct, key)
339
+ ret = Lib.memcached_server_by_key(@struct, key)
336
340
  inspect_server(ret.first) if ret.is_a?(Array)
337
341
  end
338
342
 
@@ -375,16 +379,21 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
375
379
 
376
380
  # Checks the return code from Rlibmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code and an optional key, for exception messages.
377
381
  def check_return_code(ret, key = nil) #:doc:
378
- return if ret == 0 # Lib::MEMCACHED_SUCCESS
379
- return if ret == Lib::MEMCACHED_BUFFERED
380
-
381
- if ret == Lib::MEMCACHED_NOTFOUND and !options[:show_backtraces]
382
+ if ret == 0 # Lib::MEMCACHED_SUCCESS
383
+ elsif ret == Lib::MEMCACHED_BUFFERED
384
+ elsif ret == Lib::MEMCACHED_NOTFOUND and !options[:show_backtraces]
382
385
  raise @not_found_instance
383
386
  else
384
387
  message = "Key #{inspect_keys(key, (detect_failure if ret == Lib::MEMCACHED_SERVER_MARKED_DEAD)).inspect}"
385
- if ret == Lib::MEMCACHED_ERRNO and key.is_a?(String)
386
- server = Lib.memcached_server_by_key(@struct, key)
387
- message = "Errno #{server.first.cached_errno}. #{message}"
388
+ if key.is_a?(String)
389
+ if ret == Lib::MEMCACHED_ERRNO
390
+ server = Lib.memcached_server_by_key(@struct, key)
391
+ errno = server.first.cached_errno
392
+ message = "Errno #{errno}: #{ERRNO_HASH[errno].inspect}. #{message}"
393
+ elsif ret == Lib::MEMCACHED_SERVER_ERROR
394
+ server = Lib.memcached_server_by_key(@struct, key)
395
+ message = "\"#{server.first.cached_server_error}\". #{message}."
396
+ end
388
397
  end
389
398
  raise EXCEPTIONS[ret], message
390
399
  end
@@ -398,6 +407,7 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
398
407
  end
399
408
 
400
409
  # Find which server failed most recently.
410
+ # FIXME Is this still necessary with cached_errno?
401
411
  def detect_failure
402
412
  time = Time.now
403
413
  server = server_structs.detect do |server|
@@ -408,12 +418,16 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
408
418
 
409
419
  # Set the servers on the struct.
410
420
  def set_servers(servers)
421
+ add_method = options[:use_udp] ? "memcached_server_add_udp_with_weight" : "memcached_server_add_with_weight"
411
422
  Array(servers).each_with_index do |server, index|
412
- unless server.is_a? String and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
413
- raise ArgumentError, "Servers must be in the format host:port[:weight] (e.g., 'localhost:11211' or 'localhost:11211:10')"
423
+ if server.is_a?(String) and File.socket?(server)
424
+ Lib.memcached_server_add_unix_socket_with_weight(@struct, server, options[:default_weight].to_i)
425
+ elsif server.is_a?(String) and server =~ /^[\w\d\.-]+(:\d{1,5}){0,2}$/
426
+ host, port, weight = server.split(":")
427
+ Lib.memcached_server_add_with_weight(@struct, host, port.to_i, (weight || options[:default_weight]).to_i)
428
+ else
429
+ raise ArgumentError, "Servers must be either in the format 'host:port[:weight]' (e.g., 'localhost:11211' or 'localhost:11211:10') for a network server, or a valid path to a Unix domain socket (e.g., /var/run/memcached)."
414
430
  end
415
- host, port, weight = server.split(":")
416
- Lib.memcached_server_add_with_weight(@struct, host, port.to_i, (weight || options[:default_weight]).to_i)
417
431
  end
418
432
  # For inspect
419
433
  @servers = send(:servers)
@@ -424,6 +438,8 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
424
438
  BEHAVIORS.keys.each do |behavior|
425
439
  set_behavior(behavior, options[behavior]) if options.key?(behavior)
426
440
  end
441
+ # BUG Hash must be last due to the weird Libmemcached multi-behaviors
442
+ set_behavior(:hash, options[:hash])
427
443
  end
428
444
 
429
445
  # Set the callbacks on the struct from the current options.
@@ -437,9 +453,17 @@ Please note that when pipelining is enabled, setter and deleter methods do not r
437
453
  end
438
454
  end
439
455
 
440
- # Stringify an opaque server struct.
441
- def inspect_server(server)
442
- "#{server.hostname}:#{server.port}#{":#{server.weight}" if options[:ketama_weighted]}"
456
+ def is_unix_socket?(server)
457
+ server.type == Lib::MEMCACHED_CONNECTION_UNIX_SOCKET
443
458
  end
444
459
 
460
+ # Stringify an opaque server struct
461
+ def inspect_server(server)
462
+ strings = [server.hostname]
463
+ if !is_unix_socket?(server)
464
+ strings << ":#{server.port}"
465
+ strings << ":#{server.weight}" if options[:ketama_weighted]
466
+ end
467
+ strings.join
468
+ end
445
469
  end
@@ -25,19 +25,27 @@ class Memcached
25
25
  super(key, !raw)
26
26
  rescue NotFound
27
27
  end
28
+
29
+ # Wraps Memcached#cas so that it doesn't raise. Doesn't set anything if no value is present.
30
+ def cas(key, ttl=@default_ttl, raw=false, &block)
31
+ super(key, ttl, !raw, &block)
32
+ rescue NotFound
33
+ end
34
+
35
+ alias :compare_and_swap :cas
28
36
 
29
- # Wraps Memcached#get with multiple arguments.
30
- def get_multi(*keys)
31
- super(keys)
37
+ # Wraps Memcached#get.
38
+ def get_multi(keys, raw=false)
39
+ super(keys, !raw)
32
40
  end
33
41
 
34
42
  # Wraps Memcached#set.
35
- def set(key, value, ttl=nil, raw=false)
43
+ def set(key, value, ttl=@default_ttl, raw=false)
36
44
  super(key, value, ttl, !raw)
37
45
  end
38
46
 
39
47
  # Wraps Memcached#add so that it doesn't raise.
40
- def add(key, value, ttl=nil, raw=false)
48
+ def add(key, value, ttl=@default_ttl, raw=false)
41
49
  super(key, value, ttl, !raw)
42
50
  true
43
51
  rescue NotStored
@@ -2,37 +2,33 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{memcached}
5
- s.version = "0.14"
5
+ s.version = "0.15"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Evan Weaver"]
9
9
  s.cert_chain = ["/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-public_cert.pem"]
10
- s.date = %q{2009-02-02}
10
+ s.date = %q{2009-08-03}
11
11
  s.description = %q{An interface to the libmemcached C client.}
12
12
  s.email = %q{}
13
13
  s.extensions = ["ext/extconf.rb"]
14
14
  s.extra_rdoc_files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "README", "TODO"]
15
- s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "Rakefile", "README", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO", "memcached.gemspec"]
16
- s.has_rdoc = true
15
+ s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/libmemcached-0.31.tar.gz", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "memcached.gemspec", "Rakefile", "README", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO"]
17
16
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
18
17
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Memcached", "--main", "README"]
19
18
  s.require_paths = ["lib", "ext"]
20
19
  s.rubyforge_project = %q{fauna}
21
- s.rubygems_version = %q{1.3.1}
20
+ s.rubygems_version = %q{1.3.4}
22
21
  s.signing_key = %q{/Users/eweaver/p/configuration/gem_certificates/evan_weaver-original-private_key.pem}
23
22
  s.summary = %q{An interface to the libmemcached C client.}
24
23
  s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
25
24
 
26
25
  if s.respond_to? :specification_version then
27
26
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
- s.specification_version = 2
27
+ s.specification_version = 3
29
28
 
30
29
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
- s.add_development_dependency(%q<echoe>, [">= 0"])
32
30
  else
33
- s.add_dependency(%q<echoe>, [">= 0"])
34
31
  end
35
32
  else
36
- s.add_dependency(%q<echoe>, [">= 0"])
37
33
  end
38
34
  end
@@ -1,6 +1,7 @@
1
1
 
2
2
  HERE = File.dirname(__FILE__)
3
3
  $LOAD_PATH << "#{HERE}/../../lib/"
4
+ UNIX_SOCKET_NAME = File.join(ENV['TMPDIR']||'/tmp','memcached')
4
5
 
5
6
  require 'memcached'
6
7
 
@@ -39,7 +40,7 @@ class Bench
39
40
  @value = []
40
41
  @marshalled = Marshal.dump(@value)
41
42
 
42
- @opts = [
43
+ @opts_networked = [
43
44
  ['127.0.0.1:43042', '127.0.0.1:43043'],
44
45
  {
45
46
  :buffer_requests => false,
@@ -47,6 +48,14 @@ class Bench
47
48
  :namespace => "namespace"
48
49
  }
49
50
  ]
51
+ @opt_unix = [
52
+ ["#{UNIX_SOCKET_NAME}0","#{UNIX_SOCKET_NAME}1"],
53
+ {
54
+ :buffer_requests => false,
55
+ :no_block => false,
56
+ :namespace => "namespace"
57
+ }
58
+ ]
50
59
  @key1 = "Short"
51
60
  @key2 = "Sym1-2-3::45"*8
52
61
  @key3 = "Long"*40
@@ -78,16 +87,16 @@ class Bench
78
87
  end
79
88
 
80
89
  def benchmark
81
- Benchmark.bm(31) do |x|
90
+ Benchmark.bm(35) do |x|
82
91
 
83
- n = 2500
92
+ n = (ENV["LOOPS"] || 10000).to_i
84
93
 
85
94
  if defined? Memcached
86
95
  @m = Memcached.new(
87
- @opts[0],
88
- @opts[1].merge(:no_block => true, :buffer_requests => true)
96
+ @opts_networked[0],
97
+ @opts_networked[1].merge(:no_block => true, :buffer_requests => true)
89
98
  )
90
- x.report("set:plain:noblock:memcached") do
99
+ x.report("set:plain:noblock:memcached:net") do
91
100
  n.times do
92
101
  @m.set @key1, @marshalled, 0, false
93
102
  @m.set @key2, @marshalled, 0, false
@@ -97,8 +106,22 @@ class Bench
97
106
  @m.set @key3, @marshalled, 0, false
98
107
  end
99
108
  end
100
- @m = Memcached.new(*@opts)
101
- x.report("set:plain:memcached") do
109
+ @m = Memcached.new(
110
+ @opt_unix[0],
111
+ @opt_unix[1].merge(:no_block => true, :buffer_requests => true)
112
+ )
113
+ x.report("set:plain:noblock:memcached:uds") do
114
+ n.times do
115
+ @m.set @key1, @marshalled, 0, false
116
+ @m.set @key2, @marshalled, 0, false
117
+ @m.set @key3, @marshalled, 0, false
118
+ @m.set @key1, @marshalled, 0, false
119
+ @m.set @key2, @marshalled, 0, false
120
+ @m.set @key3, @marshalled, 0, false
121
+ end
122
+ end
123
+ @m = Memcached.new(*@opts_networked)
124
+ x.report("set:plain:memcached:net") do
102
125
  n.times do
103
126
  @m.set @key1, @marshalled, 0, false
104
127
  @m.set @key2, @marshalled, 0, false
@@ -108,10 +131,21 @@ class Bench
108
131
  @m.set @key3, @marshalled, 0, false
109
132
  end
110
133
  end # if false
134
+ @m = Memcached.new(*@opt_unix)
135
+ x.report("set:plain:memcached:uds") do
136
+ n.times do
137
+ @m.set @key1, @marshalled, 0, false
138
+ @m.set @key2, @marshalled, 0, false
139
+ @m.set @key3, @marshalled, 0, false
140
+ @m.set @key1, @marshalled, 0, false
141
+ @m.set @key2, @marshalled, 0, false
142
+ @m.set @key3, @marshalled, 0, false
143
+ end
144
+ end
111
145
  end
112
146
  # Not supported by Caffeine
113
147
  if defined? MemCache
114
- @m = MemCache.new(*@opts)
148
+ @m = MemCache.new(*@opts_networked)
115
149
  x.report("set:plain:memcache-client") do
116
150
  n.times do
117
151
  @m.set @key1, @marshalled, 0, true
@@ -129,10 +163,10 @@ class Bench
129
163
 
130
164
  if defined? Memcached
131
165
  @m = Memcached.new(
132
- @opts[0],
133
- @opts[1].merge(:no_block => true, :buffer_requests => true)
166
+ @opts_networked[0],
167
+ @opts_networked[1].merge(:no_block => true, :buffer_requests => true)
134
168
  )
135
- x.report("set:ruby:noblock:memcached") do
169
+ x.report("set:ruby:noblock:memcached:net") do
136
170
  n.times do
137
171
  @m.set @key1, @value
138
172
  @m.set @key2, @value
@@ -142,8 +176,22 @@ class Bench
142
176
  @m.set @key3, @value
143
177
  end
144
178
  end
145
- @m = Memcached.new(*@opts)
146
- x.report("set:ruby:memcached") do
179
+ @m = Memcached.new(
180
+ @opt_unix[0],
181
+ @opt_unix[1].merge(:no_block => true, :buffer_requests => true)
182
+ )
183
+ x.report("set:ruby:noblock:memcached:uds") do
184
+ n.times do
185
+ @m.set @key1, @value
186
+ @m.set @key2, @value
187
+ @m.set @key3, @value
188
+ @m.set @key1, @value
189
+ @m.set @key2, @value
190
+ @m.set @key3, @value
191
+ end
192
+ end
193
+ @m = Memcached.new(*@opts_networked)
194
+ x.report("set:ruby:memcached:net") do
147
195
  n.times do
148
196
  @m.set @key1, @value
149
197
  @m.set @key2, @value
@@ -153,9 +201,20 @@ class Bench
153
201
  @m.set @key3, @value
154
202
  end
155
203
  end # if false
204
+ @m = Memcached.new(*@opt_unix)
205
+ x.report("set:ruby:memcached:uds") do
206
+ n.times do
207
+ @m.set @key1, @value
208
+ @m.set @key2, @value
209
+ @m.set @key3, @value
210
+ @m.set @key1, @value
211
+ @m.set @key2, @value
212
+ @m.set @key3, @value
213
+ end
214
+ end
156
215
  end
157
216
  if defined? Caffeine
158
- @m = Caffeine::MemCache.new(@opts[1]); @m.servers = @opts[0]
217
+ @m = Caffeine::MemCache.new(@opts_networked[1]); @m.servers = @opts_networked[0]
159
218
  x.report("set:ruby:caffeine") do
160
219
  n.times do
161
220
  @m.set @key1, @value
@@ -168,7 +227,7 @@ class Bench
168
227
  end
169
228
  end
170
229
  if defined? MemCache
171
- @m = MemCache.new(*@opts)
230
+ @m = MemCache.new(*@opts_networked)
172
231
  x.report("set:ruby:memcache-client") do
173
232
  n.times do
174
233
  @m.set @key1, @value
@@ -182,8 +241,19 @@ class Bench
182
241
  end
183
242
 
184
243
  if defined? Memcached
185
- @m = Memcached.new(*@opts)
186
- x.report("get:plain:memcached") do
244
+ @m = Memcached.new(*@opts_networked)
245
+ x.report("get:plain:memcached:net") do
246
+ n.times do
247
+ @m.get @key1, false
248
+ @m.get @key2, false
249
+ @m.get @key3, false
250
+ @m.get @key1, false
251
+ @m.get @key2, false
252
+ @m.get @key3, false
253
+ end
254
+ end
255
+ @m = Memcached.new(*@opt_unix)
256
+ x.report("get:plain:memcached:uds") do
187
257
  n.times do
188
258
  @m.get @key1, false
189
259
  @m.get @key2, false
@@ -196,7 +266,7 @@ class Bench
196
266
  end
197
267
  # Not supported by Caffeine
198
268
  if defined? MemCache
199
- @m = MemCache.new(*@opts)
269
+ @m = MemCache.new(*@opts_networked)
200
270
  x.report("get:plain:memcache-client") do
201
271
  n.times do
202
272
  @m.get @key1, true
@@ -210,8 +280,19 @@ class Bench
210
280
  end
211
281
 
212
282
  if defined? Memcached
213
- @m = Memcached.new(*@opts)
214
- x.report("get:ruby:memcached") do
283
+ @m = Memcached.new(*@opts_networked)
284
+ x.report("get:ruby:memcached:net") do
285
+ n.times do
286
+ @m.get @key1
287
+ @m.get @key2
288
+ @m.get @key3
289
+ @m.get @key1
290
+ @m.get @key2
291
+ @m.get @key3
292
+ end
293
+ end
294
+ @m = Memcached.new(*@opt_unix)
295
+ x.report("get:ruby:memcached:uds") do
215
296
  n.times do
216
297
  @m.get @key1
217
298
  @m.get @key2
@@ -223,7 +304,7 @@ class Bench
223
304
  end
224
305
  end
225
306
  if defined? Caffeine
226
- @m = Caffeine::MemCache.new(@opts[1]); @m.servers = @opts[0]
307
+ @m = Caffeine::MemCache.new(@opts_networked[1]); @m.servers = @opts_networked[0]
227
308
  x.report("get:ruby:caffeine") do
228
309
  n.times do
229
310
  @m.get @key1
@@ -236,7 +317,7 @@ class Bench
236
317
  end
237
318
  end
238
319
  if defined? MemCache
239
- @m = MemCache.new(*@opts)
320
+ @m = MemCache.new(*@opts_networked)
240
321
  x.report("get:ruby:memcache-client") do
241
322
  n.times do
242
323
  @m.get @key1
@@ -250,19 +331,29 @@ class Bench
250
331
  end
251
332
 
252
333
  if defined? Memcached
253
- @m = Memcached.new(*@opts)
334
+ @m = Memcached.new(*@opts_networked)
335
+
336
+ # Avoid rebuilding the array every request
337
+ keys = [@key1, @key2, @key3, @key4, @key5, @key6]
338
+
339
+ x.report("multiget:ruby:memcached:net") do
340
+ n.times do
341
+ @m.get keys
342
+ end
343
+ end
344
+ @m = Memcached.new(*@opt_unix)
254
345
 
255
346
  # Avoid rebuilding the array every request
256
347
  keys = [@key1, @key2, @key3, @key4, @key5, @key6]
257
348
 
258
- x.report("multiget:ruby:memcached") do
349
+ x.report("multiget:ruby:memcached:uds") do
259
350
  n.times do
260
351
  @m.get keys
261
352
  end
262
353
  end
263
354
  end
264
355
  if defined? Caffeine
265
- @m = Caffeine::MemCache.new(@opts[1]); @m.servers = @opts[0]
356
+ @m = Caffeine::MemCache.new(@opts_networked[1]); @m.servers = @opts_networked[0]
266
357
  x.report("multiget:ruby:caffeine") do
267
358
  n.times do
268
359
  # We don't use the keys array because splat is slow
@@ -271,7 +362,7 @@ class Bench
271
362
  end
272
363
  end
273
364
  if defined? MemCache
274
- @m = MemCache.new(*@opts)
365
+ @m = MemCache.new(*@opts_networked)
275
366
  x.report("multiget:ruby:memcache-client") do
276
367
  n.times do
277
368
  # We don't use the keys array because splat is slow
@@ -283,8 +374,19 @@ class Bench
283
374
  # restart_servers
284
375
 
285
376
  if defined? Memcached
286
- @m = Memcached.new(*@opts)
287
- x.report("missing:ruby:memcached") do
377
+ @m = Memcached.new(*@opts_networked)
378
+ x.report("missing:ruby:memcached:net") do
379
+ n.times do
380
+ begin @m.delete @key1; rescue Memcached::NotFound; end
381
+ begin @m.get @key1; rescue Memcached::NotFound; end
382
+ begin @m.delete @key2; rescue Memcached::NotFound; end
383
+ begin @m.get @key2; rescue Memcached::NotFound; end
384
+ begin @m.delete @key3; rescue Memcached::NotFound; end
385
+ begin @m.get @key3; rescue Memcached::NotFound; end
386
+ end
387
+ end
388
+ @m = Memcached.new(*@opt_unix)
389
+ x.report("missing:ruby:memcached:uds") do
288
390
  n.times do
289
391
  begin @m.delete @key1; rescue Memcached::NotFound; end
290
392
  begin @m.get @key1; rescue Memcached::NotFound; end
@@ -296,7 +398,7 @@ class Bench
296
398
  end
297
399
  end
298
400
  if defined? Memcached
299
- @m = Memcached.new(*@opts)
401
+ @m = Memcached.new(*@opts_networked)
300
402
  x.report("missing:ruby:memcached:inline") do
301
403
  n.times do
302
404
  @m.delete @key1 rescue nil
@@ -307,9 +409,20 @@ class Bench
307
409
  @m.get @key3 rescue nil
308
410
  end
309
411
  end
412
+ @m = Memcached.new(*@opt_unix)
413
+ x.report("missing:ruby:memcached_UDS:inline") do
414
+ n.times do
415
+ @m.delete @key1 rescue nil
416
+ @m.get @key1 rescue nil
417
+ @m.delete @key2 rescue nil
418
+ @m.get @key2 rescue nil
419
+ @m.delete @key3 rescue nil
420
+ @m.get @key3 rescue nil
421
+ end
422
+ end
310
423
  end
311
424
  if defined? Caffeine
312
- @m = Caffeine::MemCache.new(@opts[1]); @m.servers = @opts[0]
425
+ @m = Caffeine::MemCache.new(@opts_networked[1]); @m.servers = @opts_networked[0]
313
426
  x.report("missing:ruby:caffeine") do
314
427
  n.times do
315
428
  begin @m.delete @key1; rescue; end
@@ -322,7 +435,7 @@ class Bench
322
435
  end
323
436
  end
324
437
  if defined? MemCache
325
- @m = MemCache.new(*@opts)
438
+ @m = MemCache.new(*@opts_networked)
326
439
  x.report("missing:ruby:memcache-client") do
327
440
  n.times do
328
441
  begin @m.delete @key1; rescue; end
@@ -339,10 +452,10 @@ class Bench
339
452
 
340
453
  if defined? Memcached
341
454
  @m = Memcached.new(
342
- @opts[0],
343
- @opts[1].merge(:no_block => true, :buffer_requests => true)
455
+ @opts_networked[0],
456
+ @opts_networked[1].merge(:no_block => true, :buffer_requests => true)
344
457
  )
345
- x.report("mixed:ruby:noblock:memcached") do
458
+ x.report("mixed:ruby:noblock:memcached:net") do
346
459
  n.times do
347
460
  @m.set @key1, @value
348
461
  @m.set @key2, @value
@@ -358,8 +471,45 @@ class Bench
358
471
  @m.get @key3
359
472
  end
360
473
  end
361
- @m = Memcached.new(*@opts)
362
- x.report("mixed:ruby:memcached") do
474
+ @m = Memcached.new(
475
+ @opt_unix[0],
476
+ @opt_unix[1].merge(:no_block => true, :buffer_requests => true)
477
+ )
478
+ x.report("mixed:ruby:noblock:memcached:uds") do
479
+ n.times do
480
+ @m.set @key1, @value
481
+ @m.set @key2, @value
482
+ @m.set @key3, @value
483
+ @m.get @key1
484
+ @m.get @key2
485
+ @m.get @key3
486
+ @m.set @key1, @value
487
+ @m.get @key1
488
+ @m.set @key2, @value
489
+ @m.get @key2
490
+ @m.set @key3, @value
491
+ @m.get @key3
492
+ end
493
+ end
494
+ @m = Memcached.new(*@opts_networked)
495
+ x.report("mixed:ruby:memcached:net") do
496
+ n.times do
497
+ @m.set @key1, @value
498
+ @m.set @key2, @value
499
+ @m.set @key3, @value
500
+ @m.get @key1
501
+ @m.get @key2
502
+ @m.get @key3
503
+ @m.set @key1, @value
504
+ @m.get @key1
505
+ @m.set @key2, @value
506
+ @m.get @key2
507
+ @m.set @key3, @value
508
+ @m.get @key3
509
+ end
510
+ end # if false
511
+ @m = Memcached.new(*@opt_unix)
512
+ x.report("mixed:ruby:memcached:uds") do
363
513
  n.times do
364
514
  @m.set @key1, @value
365
515
  @m.set @key2, @value
@@ -377,7 +527,7 @@ class Bench
377
527
  end # if false
378
528
  end
379
529
  if defined? Caffeine
380
- @m = Caffeine::MemCache.new(@opts[1]); @m.servers = @opts[0]
530
+ @m = Caffeine::MemCache.new(@opts_networked[1]); @m.servers = @opts_networked[0]
381
531
  x.report("mixed:ruby:caffeine") do
382
532
  n.times do
383
533
  @m.set @key1, @value
@@ -396,7 +546,7 @@ class Bench
396
546
  end
397
547
  end
398
548
  if defined? MemCache
399
- @m = MemCache.new(*@opts)
549
+ @m = MemCache.new(*@opts_networked)
400
550
  x.report("mixed:ruby:memcache-client") do
401
551
  n.times do
402
552
  @m.set @key1, @value
@@ -419,17 +569,16 @@ class Bench
419
569
 
420
570
  if defined? Memcached
421
571
  unless ARGV.include? "--no-hash"
422
- n = 10000
423
- Memcached::HASH_VALUES.each do |mode,|
424
- @m = Memcached.new(@opts[0], @opts[1].merge(:hash => mode))
425
- x.report("hash:#{mode}:memcached") do
572
+ Memcached::HASH_VALUES.each do |mode, int|
573
+ @m = Memcached.new(@opt_unix[0], @opt_unix[1].merge(:hash => mode))
574
+ x.report("hash:#{mode}") do
426
575
  n.times do
427
- @m.set @key1, @marshalled, 0, false
428
- @m.get @key1, false
429
- @m.set @key2, @marshalled, 0, false
430
- @m.get @key2, false
431
- @m.set @key3, @marshalled, 0, false
432
- @m.get @key3, false
576
+ Rlibmemcached.memcached_generate_hash_rvalue(@key1, int)
577
+ Rlibmemcached.memcached_generate_hash_rvalue(@key2, int)
578
+ Rlibmemcached.memcached_generate_hash_rvalue(@key3, int)
579
+ Rlibmemcached.memcached_generate_hash_rvalue(@key4, int)
580
+ Rlibmemcached.memcached_generate_hash_rvalue(@key5, int)
581
+ Rlibmemcached.memcached_generate_hash_rvalue(@key6, int)
433
582
  end
434
583
  end
435
584
  end