memcached 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- :no_block => false
16
+ :namespace => nil
13
17
  }
14
18
 
15
- IGNORED = 0
19
+ IGNORED = 0 #:nodoc:
16
20
 
17
- attr_reader :namespace
18
- attr_reader :options
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
- alias :dup :clone
96
+ #:stopdoc:
97
+ alias :dup :clone #:nodoc:
98
+ #:startdoc:
63
99
 
64
- ### Configuration helpers
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
- ### Operations
113
+ ###### Operations
77
114
 
78
115
  public
79
116
 
80
- # Setters
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
- def cas
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
- # Deleters
202
+ ### Deleters
139
203
 
140
- def delete(key, timeout=0)
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), timeout)
207
+ Libmemcached.memcached_delete(@struct, ns(key), IGNORED)
143
208
  )
144
209
  end
145
210
 
146
- # Getters
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
- # XXX Not sure how this behavior should be defined
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. Possibly a performance problem.
162
- raise ClientError, "Invalid key" if !key.is_a? String or key =~ /\s/
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
- # Information methods
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
- def ns(key)
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
- def check_return_code(ret)
214
- return if ret == 0
215
- raise @@exceptions[ret]
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.5
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.5"
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-20}
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.h", "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_test.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "memcached.gemspec"]
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/benchmark/benchmark_test.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb"]
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