memcached 0.14 → 0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -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