memcached 0.5 → 0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +2 -0
- data/Manifest +4 -2
- data/README +95 -11
- data/TODO +11 -0
- data/ext/extconf.rb +9 -1
- data/ext/libmemcached.i +12 -1
- data/ext/libmemcached_wrap.c +140 -0
- data/lib/memcached.rb +17 -0
- data/lib/memcached/behaviors.rb +6 -1
- data/lib/memcached/exceptions.rb +53 -8
- data/lib/memcached/memcached.rb +111 -35
- data/memcached.gemspec +18 -5
- data/test/benchmark/benchmark.rb +259 -0
- data/test/benchmark/benchmark_set_get.rb +56 -0
- data/test/benchmark/profile.rb +49 -0
- data/test/setup.rb +7 -5
- data/test/unit/memcached_test.rb +109 -18
- metadata +6 -5
- metadata.gz.sig +0 -0
- data/ext/libmemcached.h +0 -425
- data/test/benchmark/benchmark_test.rb +0 -42
data/lib/memcached/memcached.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
|
2
|
+
=begin rdoc
|
3
|
+
The Memcached client class.
|
4
|
+
=end
|
2
5
|
class Memcached
|
3
6
|
|
4
7
|
FLAGS = 0x0
|
@@ -6,19 +9,38 @@ class Memcached
|
|
6
9
|
DEFAULTS = {
|
7
10
|
:hash => :default,
|
8
11
|
:distribution => :consistent,
|
12
|
+
:no_block => false,
|
9
13
|
:buffer_requests => false,
|
10
14
|
:support_cas => false,
|
11
15
|
:tcp_nodelay => false,
|
12
|
-
:
|
16
|
+
:namespace => nil
|
13
17
|
}
|
14
18
|
|
15
|
-
IGNORED = 0
|
19
|
+
IGNORED = 0 #:nodoc:
|
16
20
|
|
17
|
-
attr_reader :
|
18
|
-
|
21
|
+
attr_reader :options # Return the options Hash used to configure this instance.
|
22
|
+
|
23
|
+
###### Configuration
|
24
|
+
|
25
|
+
=begin rdoc
|
26
|
+
Create a new Memcached instance. Accepts a single server string such as '127.0.0.1:11211', or an array of such strings, as well an an optional configuration hash.
|
27
|
+
|
28
|
+
Hostname lookups are not currently supported; you need to use the IP address.
|
29
|
+
|
30
|
+
Valid option parameters are:
|
31
|
+
|
32
|
+
<tt>:namespace</tt>:: A namespace string to prepend to every key.
|
33
|
+
<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>:ketama</tt>, and <tt>:md5</tt>. <tt>:default</tt> is the fastest.
|
34
|
+
<tt>:distribution</tt>:: The type of distribution function to use. Possible values are <tt>:modula</tt> and <tt>:consistent</tt>. Note that this is decoupled from the choice of hash function.
|
35
|
+
<tt>:support_cas</tt>:: Flag CAS support in the client. Accepts <tt>true</tt> or <tt>false</tt>. Note that your server must also support CAS or you will trigger <b>Memcached::ProtocolError</b> exceptions.
|
36
|
+
<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.
|
37
|
+
<tt>:no_block</tt>:: Whether to use non-blocking, asynchronous IO for writes. Accepts <tt>true</tt> or <tt>false</tt>.
|
38
|
+
<tt>:buffer_requests</tt>:: Whether to use an internal write buffer. Accepts <tt>true</tt> or <tt>false</tt>. Calling <tt>get</tt> or closing the connection will force the buffer to flush. Note that <tt>:buffer_requests</tt> might not work well without <tt>:no_block</tt> also enabled.
|
39
|
+
|
40
|
+
Please note that when non-blocking IO is enabled, setter and deleter methods do not raise on errors. For example, if you try to set an invalid key with <tt>:no_block => true</tt>, it will appear to succeed. The actual setting of the key occurs after libmemcached has returned control to your program, so there is no way to backtrack and raise the exception.
|
41
|
+
|
42
|
+
=end
|
19
43
|
|
20
|
-
### Configuration
|
21
|
-
|
22
44
|
def initialize(servers, opts = {})
|
23
45
|
@struct = Libmemcached::MemcachedSt.new
|
24
46
|
Libmemcached.memcached_create(@struct)
|
@@ -37,34 +59,49 @@ class Memcached
|
|
37
59
|
)
|
38
60
|
end
|
39
61
|
|
40
|
-
# Namespace
|
41
|
-
@namespace = opts[:namespace]
|
42
|
-
raise ArgumentError, "Invalid namespace" if namespace.to_s =~ / /
|
43
|
-
|
44
62
|
# Behaviors
|
45
63
|
@options = DEFAULTS.merge(opts)
|
46
64
|
options.each do |option, value|
|
47
65
|
set_behavior(option, value) unless option == :namespace
|
48
66
|
end
|
67
|
+
|
68
|
+
# Make sure :buffer_requests uses :no_block
|
69
|
+
# XXX Not enforcing this for now.
|
70
|
+
# if options[:buffer_requests] and not options[:no_block]
|
71
|
+
# raise ArgumentError, "Invalid options; :buffer_requests does not work well without :no_block."
|
72
|
+
# end
|
73
|
+
|
74
|
+
# Namespace
|
75
|
+
raise ArgumentError, "Invalid namespace" if options[:namespace].to_s =~ / /
|
76
|
+
@namespace = options[:namespace]
|
49
77
|
end
|
50
78
|
|
79
|
+
=begin rdoc
|
80
|
+
Return the array of server strings used to configure this instance.
|
81
|
+
=end
|
51
82
|
def servers
|
52
83
|
server_structs.map do |server|
|
53
84
|
"#{server.hostname}:#{server.port}"
|
54
85
|
end
|
55
86
|
end
|
56
|
-
|
87
|
+
|
88
|
+
# Safely copy this instance. Returns a Memcached instance.
|
89
|
+
#
|
90
|
+
# <tt>clone</tt> is useful for threading, since each thread must have its own unshared Memcached object.
|
57
91
|
def clone
|
58
92
|
# XXX Could be more efficient if we used Libmemcached.memcached_clone(@struct)
|
59
93
|
self.class.new(servers, options)
|
60
94
|
end
|
61
95
|
|
62
|
-
|
96
|
+
#:stopdoc:
|
97
|
+
alias :dup :clone #:nodoc:
|
98
|
+
#:startdoc:
|
63
99
|
|
64
|
-
|
100
|
+
### Configuration helpers
|
65
101
|
|
66
102
|
private
|
67
103
|
|
104
|
+
# Return an array of raw <tt>memcached_host_st</tt> structs for this instance.
|
68
105
|
def server_structs
|
69
106
|
array = []
|
70
107
|
@struct.hosts.count.times do |i|
|
@@ -73,12 +110,18 @@ class Memcached
|
|
73
110
|
array
|
74
111
|
end
|
75
112
|
|
76
|
-
|
113
|
+
###### Operations
|
77
114
|
|
78
115
|
public
|
79
116
|
|
80
|
-
|
81
|
-
|
117
|
+
### Setters
|
118
|
+
|
119
|
+
# Set a key/value pair. Accepts a String <tt>key</tt> and an arbitrary Ruby object. Overwrites any existing value on the server.
|
120
|
+
#
|
121
|
+
# Accepts an optional <tt>timeout</tt> value to specify the maximum lifetime of the key on the server. <tt>timeout</tt> can be either an integer number of seconds, or a Time elapsed time object. (There is no guarantee that the key will persist as long as the <tt>timeout</tt>, but it will not persist longer.)
|
122
|
+
#
|
123
|
+
# 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.
|
124
|
+
#
|
82
125
|
def set(key, value, timeout=0, marshal=true)
|
83
126
|
value = marshal ? Marshal.dump(value) : value.to_s
|
84
127
|
check_return_code(
|
@@ -86,35 +129,48 @@ class Memcached
|
|
86
129
|
)
|
87
130
|
end
|
88
131
|
|
132
|
+
# 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>.
|
89
133
|
def add(key, value, timeout=0, marshal=true)
|
90
134
|
value = marshal ? Marshal.dump(value) : value.to_s
|
91
135
|
check_return_code(
|
92
136
|
Libmemcached.memcached_add(@struct, ns(key), value, timeout, FLAGS)
|
93
137
|
)
|
94
138
|
end
|
95
|
-
|
139
|
+
|
140
|
+
# Increment a key's value. Accepts a String <tt>key</tt>. Raises <b>Memcached::NotFound</b> if the key does not exist.
|
141
|
+
#
|
142
|
+
# Also accepts an optional <tt>offset</tt> paramater, which defaults to 1. <tt>offset</tt> must be an integer.
|
143
|
+
#
|
144
|
+
# Note that the key must be initialized to an unmarshalled integer first, via <tt>set</tt>, <tt>add</tt>, or <tt>replace</tt> with <tt>marshal</tt> set to <tt>false</tt>.
|
96
145
|
def increment(key, offset=1)
|
97
146
|
ret, value = Libmemcached.memcached_increment(@struct, ns(key), offset)
|
98
147
|
check_return_code(ret)
|
99
148
|
value
|
100
149
|
end
|
101
|
-
|
150
|
+
|
151
|
+
# Decrement a key's value. The parameters and exception behavior are the same as <tt>increment</tt>.
|
102
152
|
def decrement(key, offset=1)
|
103
153
|
ret, value = Libmemcached.memcached_decrement(@struct, ns(key), offset)
|
104
154
|
check_return_code(ret)
|
105
155
|
value
|
106
156
|
end
|
107
157
|
|
158
|
+
#:stopdoc:
|
108
159
|
alias :incr :increment
|
109
160
|
alias :decr :decrement
|
110
|
-
|
161
|
+
#:startdoc:
|
162
|
+
|
163
|
+
# 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>.
|
111
164
|
def replace(key, value, timeout=0, marshal=true)
|
112
165
|
value = marshal ? Marshal.dump(value) : value.to_s
|
113
166
|
check_return_code(
|
114
167
|
Libmemcached.memcached_replace(@struct, ns(key), value, timeout, FLAGS)
|
115
168
|
)
|
116
169
|
end
|
117
|
-
|
170
|
+
|
171
|
+
# Appends a string to a key's value. Accepts a String <tt>key</tt> and a String <tt>value</tt>. Raises <b>Memcached::NotFound</b> if the key does not exist on the server.
|
172
|
+
#
|
173
|
+
# Note that the key must be initialized to an unmarshalled string first, via <tt>set</tt>, <tt>add</tt>, or <tt>replace</tt> with <tt>marshal</tt> set to <tt>false</tt>.
|
118
174
|
def append(key, value)
|
119
175
|
# Requires memcached 1.2.4
|
120
176
|
check_return_code(
|
@@ -122,6 +178,7 @@ class Memcached
|
|
122
178
|
)
|
123
179
|
end
|
124
180
|
|
181
|
+
# Prepends a string to a key's value. The parameters and exception behavior are the same as <tt>append</tt>.
|
125
182
|
def prepend(key, value)
|
126
183
|
# Requires memcached 1.2.4
|
127
184
|
check_return_code(
|
@@ -129,37 +186,52 @@ class Memcached
|
|
129
186
|
)
|
130
187
|
end
|
131
188
|
|
132
|
-
|
189
|
+
# Not yet implemented.
|
190
|
+
#
|
191
|
+
# Reads a key's value from the server and yields it to a block. Replaces the key's value with the result of the block as long as the key hasn't been updated in the meantime, otherwise raises <b>Memcached::NotStored</b>. Accepts a String <tt>key</tt> and a block.
|
192
|
+
#
|
193
|
+
# Also accepts an optional <tt>timeout</tt> value.
|
194
|
+
#
|
195
|
+
# 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.
|
196
|
+
def cas(*args)
|
133
197
|
# Requires memcached HEAD
|
134
198
|
raise NotImplemented
|
135
|
-
raise "CAS not enabled" unless options[:support_cas]
|
199
|
+
raise ClientError, "CAS not enabled for this Memcached instance" unless options[:support_cas]
|
136
200
|
end
|
137
201
|
|
138
|
-
|
202
|
+
### Deleters
|
139
203
|
|
140
|
-
|
204
|
+
# 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.
|
205
|
+
def delete(key)
|
141
206
|
check_return_code(
|
142
|
-
Libmemcached.memcached_delete(@struct, ns(key),
|
207
|
+
Libmemcached.memcached_delete(@struct, ns(key), IGNORED)
|
143
208
|
)
|
144
209
|
end
|
145
210
|
|
146
|
-
|
211
|
+
### Getters
|
147
212
|
|
213
|
+
# Gets a key's value from the server. Accepts a String <tt>key</tt> or array of String <tt>keys</tt>.
|
214
|
+
#
|
215
|
+
# 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 returned directly as a String. Otherwise it will be assumed to be a marshalled Ruby object and unmarshalled.
|
216
|
+
#
|
217
|
+
# If you pass a single key, and the key does not exist on the server, <b>Memcached::NotFound</b> will be raised. If you pass an array of keys, memcached's <tt>multiget</tt> mode will be used, and an array of values will be returned. Missing values in the array will be represented as instances of <b>Memcached::NotFound</b>. This behavior may change in the future.
|
218
|
+
#
|
148
219
|
def get(key, marshal=true)
|
220
|
+
# XXX Could be faster if it didn't have to branch on the key type
|
149
221
|
if key.is_a? Array
|
150
222
|
# Multi get
|
151
223
|
# XXX Waiting on the real implementation
|
152
224
|
key.map do |this_key|
|
153
225
|
begin
|
154
226
|
get(this_key, marshal)
|
155
|
-
rescue NotFound
|
156
|
-
|
227
|
+
rescue NotFound => e
|
228
|
+
e
|
157
229
|
end
|
158
230
|
end
|
159
231
|
else
|
160
232
|
# Single get
|
161
|
-
# XXX Server doesn't validate.
|
162
|
-
raise ClientError, "Invalid key" if
|
233
|
+
# XXX Server doesn't validate keys. Regex is possibly a performance problem.
|
234
|
+
raise ClientError, "Invalid key" if key =~ /\s/
|
163
235
|
|
164
236
|
value, flags, ret = Libmemcached.memcached_get_ruby_string(@struct, ns(key))
|
165
237
|
check_return_code(ret)
|
@@ -168,8 +240,9 @@ class Memcached
|
|
168
240
|
end
|
169
241
|
end
|
170
242
|
|
171
|
-
|
243
|
+
### Information methods
|
172
244
|
|
245
|
+
# Return a Hash of statistics responses from the set of servers. Each value is an array with one entry for each server, in the same order the servers were defined.
|
173
246
|
def stats
|
174
247
|
stats = Hash.new([])
|
175
248
|
|
@@ -206,13 +279,16 @@ class Memcached
|
|
206
279
|
|
207
280
|
private
|
208
281
|
|
209
|
-
|
282
|
+
# Return a namespaced key for this Memcached instance. Accepts a String <tt>key</tt> value.
|
283
|
+
def ns(key) #:doc:
|
210
284
|
"#{@namespace}#{key}"
|
211
285
|
end
|
212
286
|
|
213
|
-
|
214
|
-
|
215
|
-
|
287
|
+
# Checks the return code from Libmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code.
|
288
|
+
def check_return_code(ret) #:doc:
|
289
|
+
# XXX 0.14 already returns 0 for an ActionQueued result
|
290
|
+
return if ret == 0 or ret == 31
|
291
|
+
raise EXCEPTIONS[ret], ""
|
216
292
|
end
|
217
293
|
|
218
294
|
end
|
data/memcached.gemspec
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Memcached-0.
|
2
|
+
# Gem::Specification for Memcached-0.6
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{memcached}
|
7
|
-
s.version = "0.
|
7
|
+
s.version = "0.6"
|
8
8
|
|
9
9
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = ["Evan Weaver"]
|
13
|
-
s.date = %q{2008-01-
|
13
|
+
s.date = %q{2008-01-21}
|
14
14
|
s.description = %q{An interface to the libmemcached C client.}
|
15
15
|
s.email = %q{}
|
16
16
|
s.extensions = ["ext/extconf.rb"]
|
17
|
-
s.files = ["CHANGELOG", "ext/extconf.rb", "ext/libmemcached.
|
17
|
+
s.files = ["CHANGELOG", "ext/extconf.rb", "ext/libmemcached.i", "ext/libmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached.rb", "LICENSE", "Manifest", "README", "test/benchmark/benchmark.rb", "test/benchmark/benchmark_set_get.rb", "test/benchmark/profile.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "TODO", "memcached.gemspec"]
|
18
18
|
s.has_rdoc = true
|
19
19
|
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
|
20
20
|
s.require_paths = ["lib", "ext"]
|
21
21
|
s.rubyforge_project = %q{fauna}
|
22
22
|
s.rubygems_version = %q{1.0.1}
|
23
23
|
s.summary = %q{An interface to the libmemcached C client.}
|
24
|
-
s.test_files = ["test/
|
24
|
+
s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb"]
|
25
25
|
end
|
26
26
|
|
27
27
|
|
@@ -35,4 +35,17 @@ end
|
|
35
35
|
# p.summary = "An interface to the libmemcached C client."
|
36
36
|
# p.url = "http://blog.evanweaver.com/files/doc/fauna/memcached/"
|
37
37
|
# p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
|
38
|
+
# p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|exceptions|behaviors|memcached.rb/
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# task :exceptions do
|
42
|
+
# $LOAD_PATH << "lib"
|
43
|
+
# require 'memcached'
|
44
|
+
# Memcached.constants.sort.each do |const_name|
|
45
|
+
# const = Memcached.send(:const_get, const_name)
|
46
|
+
# next if const == Memcached::Success or const == Memcached::Stored
|
47
|
+
# if const.is_a? Class and const < Memcached::Error
|
48
|
+
# puts "* Memcached::#{const_name}"
|
49
|
+
# end
|
50
|
+
# end
|
38
51
|
# end
|
@@ -0,0 +1,259 @@
|
|
1
|
+
|
2
|
+
HERE = File.dirname(__FILE__)
|
3
|
+
$LOAD_PATH << "#{HERE}/../../lib/"
|
4
|
+
|
5
|
+
require 'memcached'
|
6
|
+
require 'benchmark'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'memcache'
|
9
|
+
|
10
|
+
# We'll use a simple @value to try to avoid spending time in Marshal,
|
11
|
+
# which is a constant penalty that both clients have to pay
|
12
|
+
@value = []
|
13
|
+
@marshalled = Marshal.dump(@value)
|
14
|
+
|
15
|
+
@opts = [
|
16
|
+
['127.0.0.1:43042', '127.0.0.1:43043'],
|
17
|
+
{
|
18
|
+
:buffer_requests => false,
|
19
|
+
:no_block => false,
|
20
|
+
:namespace => "benchmark_namespace"
|
21
|
+
}
|
22
|
+
]
|
23
|
+
@key1 = "Short"
|
24
|
+
@key2 = "Sym1-2-3::45"*8
|
25
|
+
@key3 = "Long"*40
|
26
|
+
@key4 = "Medium"*8
|
27
|
+
|
28
|
+
def restart_servers
|
29
|
+
system("ruby #{HERE}/../setup.rb")
|
30
|
+
sleep(1)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
Benchmark.bm(31) do |x|
|
35
|
+
restart_servers
|
36
|
+
|
37
|
+
n = 1000
|
38
|
+
|
39
|
+
@m = Memcached.new(
|
40
|
+
@opts[0],
|
41
|
+
@opts[1].merge(:no_block => true, :buffer_requests => true)
|
42
|
+
)
|
43
|
+
x.report("set:plain:noblock:memcached") do
|
44
|
+
n.times do
|
45
|
+
@m.set @key1, @marshalled, 0, false
|
46
|
+
@m.set @key2, @marshalled, 0, false
|
47
|
+
@m.set @key3, @marshalled, 0, false
|
48
|
+
@m.set @key1, @marshalled, 0, false
|
49
|
+
@m.set @key2, @marshalled, 0, false
|
50
|
+
@m.set @key3, @marshalled, 0, false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@m = Memcached.new(*@opts)
|
54
|
+
x.report("set:plain:memcached") do
|
55
|
+
n.times do
|
56
|
+
@m.set @key1, @marshalled, 0, false
|
57
|
+
@m.set @key2, @marshalled, 0, false
|
58
|
+
@m.set @key3, @marshalled, 0, false
|
59
|
+
@m.set @key1, @marshalled, 0, false
|
60
|
+
@m.set @key2, @marshalled, 0, false
|
61
|
+
@m.set @key3, @marshalled, 0, false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
@m = MemCache.new(*@opts)
|
65
|
+
x.report("set:plain:memcache-client") do
|
66
|
+
n.times do
|
67
|
+
@m.set @key1, @marshalled, 0, true
|
68
|
+
@m.set @key2, @marshalled, 0, true
|
69
|
+
@m.set @key3, @marshalled, 0, true
|
70
|
+
@m.set @key1, @marshalled, 0, true
|
71
|
+
@m.set @key2, @marshalled, 0, true
|
72
|
+
@m.set @key3, @marshalled, 0, true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
restart_servers
|
77
|
+
|
78
|
+
@m = Memcached.new(
|
79
|
+
@opts[0],
|
80
|
+
@opts[1].merge(:no_block => true, :buffer_requests => true)
|
81
|
+
)
|
82
|
+
x.report("set:ruby:noblock:memcached") do
|
83
|
+
n.times do
|
84
|
+
@m.set @key1, @value
|
85
|
+
@m.set @key2, @value
|
86
|
+
@m.set @key3, @value
|
87
|
+
@m.set @key1, @value
|
88
|
+
@m.set @key2, @value
|
89
|
+
@m.set @key3, @value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
@m = Memcached.new(*@opts)
|
93
|
+
x.report("set:ruby:memcached") do
|
94
|
+
n.times do
|
95
|
+
@m.set @key1, @value
|
96
|
+
@m.set @key2, @value
|
97
|
+
@m.set @key3, @value
|
98
|
+
@m.set @key1, @value
|
99
|
+
@m.set @key2, @value
|
100
|
+
@m.set @key3, @value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
@m = MemCache.new(*@opts)
|
104
|
+
x.report("set:ruby:memcache-client") do
|
105
|
+
n.times do
|
106
|
+
@m.set @key1, @value
|
107
|
+
@m.set @key2, @value
|
108
|
+
@m.set @key3, @value
|
109
|
+
@m.set @key1, @value
|
110
|
+
@m.set @key2, @value
|
111
|
+
@m.set @key3, @value
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
@m = Memcached.new(*@opts)
|
116
|
+
x.report("get:plain:memcached") do
|
117
|
+
n.times do
|
118
|
+
@m.get @key1, false
|
119
|
+
@m.get @key2, false
|
120
|
+
@m.get @key3, false
|
121
|
+
@m.get @key1, false
|
122
|
+
@m.get @key2, false
|
123
|
+
@m.get @key3, false
|
124
|
+
end
|
125
|
+
end
|
126
|
+
@m = MemCache.new(*@opts)
|
127
|
+
x.report("get:plain:memcache-client") do
|
128
|
+
n.times do
|
129
|
+
@m.get @key1, true
|
130
|
+
@m.get @key2, true
|
131
|
+
@m.get @key3, true
|
132
|
+
@m.get @key1, true
|
133
|
+
@m.get @key2, true
|
134
|
+
@m.get @key3, true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
@m = Memcached.new(*@opts)
|
139
|
+
x.report("get:ruby:memcached") do
|
140
|
+
n.times do
|
141
|
+
@m.get @key1
|
142
|
+
@m.get @key2
|
143
|
+
@m.get @key3
|
144
|
+
@m.get @key1
|
145
|
+
@m.get @key2
|
146
|
+
@m.get @key3
|
147
|
+
end
|
148
|
+
end
|
149
|
+
@m = MemCache.new(*@opts)
|
150
|
+
x.report("get:ruby:memcache-client") do
|
151
|
+
n.times do
|
152
|
+
@m.get @key1
|
153
|
+
@m.get @key2
|
154
|
+
@m.get @key3
|
155
|
+
@m.get @key1
|
156
|
+
@m.get @key2
|
157
|
+
@m.get @key3
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
restart_servers
|
162
|
+
|
163
|
+
@m = Memcached.new(*@opts)
|
164
|
+
x.report("missing:ruby:memcached") do
|
165
|
+
n.times do
|
166
|
+
begin @m.delete @key1; rescue Memcached::NotFound; end
|
167
|
+
begin @m.get @key1; rescue Memcached::NotFound; end
|
168
|
+
begin @m.delete @key2; rescue Memcached::NotFound; end
|
169
|
+
begin @m.get @key2; rescue Memcached::NotFound; end
|
170
|
+
begin @m.delete @key3; rescue Memcached::NotFound; end
|
171
|
+
begin @m.get @key3; rescue Memcached::NotFound; end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
@m = MemCache.new(*@opts)
|
175
|
+
x.report("missing:ruby:memcache-client") do
|
176
|
+
n.times do
|
177
|
+
begin @m.delete @key1; rescue; end
|
178
|
+
begin @m.get @key1; rescue; end
|
179
|
+
begin @m.delete @key2; rescue; end
|
180
|
+
begin @m.get @key2; rescue; end
|
181
|
+
begin @m.delete @key3; rescue; end
|
182
|
+
begin @m.get @key3; rescue; end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
restart_servers
|
187
|
+
|
188
|
+
@m = Memcached.new(
|
189
|
+
@opts[0],
|
190
|
+
@opts[1].merge(:no_block => true, :buffer_requests => true)
|
191
|
+
)
|
192
|
+
x.report("mixed:ruby:noblock:memcached") do
|
193
|
+
n.times do
|
194
|
+
@m.set @key1, @value
|
195
|
+
@m.set @key2, @value
|
196
|
+
@m.set @key3, @value
|
197
|
+
@m.get @key1
|
198
|
+
@m.get @key2
|
199
|
+
@m.get @key3
|
200
|
+
@m.set @key1, @value
|
201
|
+
@m.get @key1
|
202
|
+
@m.set @key2, @value
|
203
|
+
@m.get @key2
|
204
|
+
@m.set @key3, @value
|
205
|
+
@m.get @key3
|
206
|
+
end
|
207
|
+
end
|
208
|
+
@m = Memcached.new(*@opts)
|
209
|
+
x.report("mixed:ruby:memcached") do
|
210
|
+
n.times do
|
211
|
+
@m.set @key1, @value
|
212
|
+
@m.set @key2, @value
|
213
|
+
@m.set @key3, @value
|
214
|
+
@m.get @key1
|
215
|
+
@m.get @key2
|
216
|
+
@m.get @key3
|
217
|
+
@m.set @key1, @value
|
218
|
+
@m.get @key1
|
219
|
+
@m.set @key2, @value
|
220
|
+
@m.get @key2
|
221
|
+
@m.set @key3, @value
|
222
|
+
@m.get @key3
|
223
|
+
end
|
224
|
+
end
|
225
|
+
@m = MemCache.new(*@opts)
|
226
|
+
x.report("mixed:ruby:memcache-client") do
|
227
|
+
n.times do
|
228
|
+
@m.set @key1, @value
|
229
|
+
@m.set @key2, @value
|
230
|
+
@m.set @key3, @value
|
231
|
+
@m.get @key1
|
232
|
+
@m.get @key2
|
233
|
+
@m.get @key3
|
234
|
+
@m.set @key1, @value
|
235
|
+
@m.get @key1
|
236
|
+
@m.set @key2, @value
|
237
|
+
@m.get @key2
|
238
|
+
@m.set @key3, @value
|
239
|
+
@m.get @key3
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
restart_servers
|
244
|
+
|
245
|
+
n = 10000
|
246
|
+
Memcached::HASH_VALUES.each do |mode,|
|
247
|
+
@m = Memcached.new(@opts[0], @opts[1].merge(:hash => mode))
|
248
|
+
x.report("hash:#{mode}:memcached") do
|
249
|
+
n.times do
|
250
|
+
@m.set @key1, @marshalled, 0, false
|
251
|
+
@m.get @key1, false
|
252
|
+
@m.set @key2, @marshalled, 0, false
|
253
|
+
@m.get @key2, false
|
254
|
+
@m.set @key3, @marshalled, 0, false
|
255
|
+
@m.get @key3, false
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|