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