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.
- data.tar.gz.sig +0 -0
- data/BENCHMARKS +83 -64
- data/CHANGELOG +9 -1
- data/COMPATIBILITY +2 -1
- data/Manifest +2 -0
- data/README +4 -11
- data/Rakefile +1 -0
- data/ext/extconf.rb +40 -17
- data/ext/libmemcached-0.31.tar.gz +0 -0
- data/ext/rlibmemcached.i +29 -10
- data/ext/rlibmemcached_wrap.c +3167 -1659
- data/lib/memcached/behaviors.rb +2 -2
- data/lib/memcached/exceptions.rb +4 -4
- data/lib/memcached/memcached.rb +61 -37
- data/lib/memcached/rails.rb +13 -5
- data/memcached.gemspec +5 -9
- data/test/profile/benchmark.rb +198 -49
- data/test/profile/profile.rb +3 -8
- data/test/profile/valgrind.rb +5 -12
- data/test/setup.rb +21 -16
- data/test/test_helper.rb +5 -1
- data/test/unit/memcached_test.rb +98 -30
- data/test/unit/rails_test.rb +32 -2
- metadata +10 -16
- metadata.gz.sig +0 -0
data/lib/memcached/behaviors.rb
CHANGED
@@ -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:
|
data/lib/memcached/exceptions.rb
CHANGED
@@ -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
|
data/lib/memcached/memcached.rb
CHANGED
@@ -7,7 +7,7 @@ class Memcached
|
|
7
7
|
FLAGS = 0x0
|
8
8
|
|
9
9
|
DEFAULTS = {
|
10
|
-
:hash => :
|
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 =>
|
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>:
|
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>
|
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 =
|
84
|
-
|
85
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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 =
|
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 =
|
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
|
-
|
379
|
-
|
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
|
386
|
-
|
387
|
-
|
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
|
-
|
413
|
-
|
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
|
-
|
441
|
-
|
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
|
data/lib/memcached/rails.rb
CHANGED
@@ -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
|
30
|
-
def get_multi(
|
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
|
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
|
48
|
+
def add(key, value, ttl=@default_ttl, raw=false)
|
41
49
|
super(key, value, ttl, !raw)
|
42
50
|
true
|
43
51
|
rescue NotStored
|
data/memcached.gemspec
CHANGED
@@ -2,37 +2,33 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{memcached}
|
5
|
-
s.version = "0.
|
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-
|
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"
|
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.
|
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 =
|
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
|
data/test/profile/benchmark.rb
CHANGED
@@ -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
|
-
@
|
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(
|
90
|
+
Benchmark.bm(35) do |x|
|
82
91
|
|
83
|
-
n =
|
92
|
+
n = (ENV["LOOPS"] || 10000).to_i
|
84
93
|
|
85
94
|
if defined? Memcached
|
86
95
|
@m = Memcached.new(
|
87
|
-
@
|
88
|
-
@
|
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(
|
101
|
-
|
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(*@
|
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
|
-
@
|
133
|
-
@
|
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(
|
146
|
-
|
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(@
|
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(*@
|
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(*@
|
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(*@
|
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(*@
|
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(@
|
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(*@
|
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(*@
|
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(@
|
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(*@
|
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(*@
|
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(*@
|
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(@
|
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(*@
|
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
|
-
@
|
343
|
-
@
|
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(
|
362
|
-
|
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(@
|
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(*@
|
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
|
-
|
423
|
-
|
424
|
-
|
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
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
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
|