dalli 2.0.1 → 3.2.8
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +671 -0
- data/Gemfile +15 -3
- data/LICENSE +1 -1
- data/README.md +33 -148
- data/lib/dalli/cas/client.rb +3 -0
- data/lib/dalli/client.rb +293 -131
- data/lib/dalli/compressor.rb +40 -0
- data/lib/dalli/key_manager.rb +121 -0
- data/lib/dalli/options.rb +22 -4
- data/lib/dalli/pid_cache.rb +40 -0
- data/lib/dalli/pipelined_getter.rb +177 -0
- data/lib/dalli/protocol/base.rb +250 -0
- data/lib/dalli/protocol/binary/request_formatter.rb +117 -0
- data/lib/dalli/protocol/binary/response_header.rb +36 -0
- data/lib/dalli/protocol/binary/response_processor.rb +239 -0
- data/lib/dalli/protocol/binary/sasl_authentication.rb +60 -0
- data/lib/dalli/protocol/binary.rb +173 -0
- data/lib/dalli/protocol/connection_manager.rb +255 -0
- data/lib/dalli/protocol/meta/key_regularizer.rb +31 -0
- data/lib/dalli/protocol/meta/request_formatter.rb +121 -0
- data/lib/dalli/protocol/meta/response_processor.rb +211 -0
- data/lib/dalli/protocol/meta.rb +178 -0
- data/lib/dalli/protocol/response_buffer.rb +54 -0
- data/lib/dalli/protocol/server_config_parser.rb +86 -0
- data/lib/dalli/protocol/ttl_sanitizer.rb +45 -0
- data/lib/dalli/protocol/value_compressor.rb +85 -0
- data/lib/dalli/protocol/value_marshaller.rb +59 -0
- data/lib/dalli/protocol/value_serializer.rb +91 -0
- data/lib/dalli/protocol.rb +19 -0
- data/lib/dalli/ring.rb +98 -50
- data/lib/dalli/server.rb +4 -524
- data/lib/dalli/servers_arg_normalizer.rb +54 -0
- data/lib/dalli/socket.rb +154 -53
- data/lib/dalli/version.rb +5 -1
- data/lib/dalli.rb +49 -13
- data/lib/rack/session/dalli.rb +169 -26
- metadata +53 -88
- data/History.md +0 -262
- data/Performance.md +0 -42
- data/Rakefile +0 -39
- data/dalli.gemspec +0 -28
- data/lib/action_dispatch/middleware/session/dalli_store.rb +0 -76
- data/lib/active_support/cache/dalli_store.rb +0 -203
- data/test/abstract_unit.rb +0 -281
- data/test/benchmark_test.rb +0 -187
- data/test/helper.rb +0 -41
- data/test/memcached_mock.rb +0 -113
- data/test/test_active_support.rb +0 -163
- data/test/test_dalli.rb +0 -461
- data/test/test_encoding.rb +0 -43
- data/test/test_failover.rb +0 -107
- data/test/test_network.rb +0 -54
- data/test/test_ring.rb +0 -85
- data/test/test_sasl.rb +0 -83
- data/test/test_session_store.rb +0 -224
@@ -1,203 +0,0 @@
|
|
1
|
-
# encoding: ascii
|
2
|
-
require 'dalli'
|
3
|
-
require 'digest/md5'
|
4
|
-
|
5
|
-
module ActiveSupport
|
6
|
-
module Cache
|
7
|
-
class DalliStore
|
8
|
-
|
9
|
-
ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/
|
10
|
-
|
11
|
-
# Creates a new DalliStore object, with the given memcached server
|
12
|
-
# addresses. Each address is either a host name, or a host-with-port string
|
13
|
-
# in the form of "host_name:port". For example:
|
14
|
-
#
|
15
|
-
# ActiveSupport::Cache::DalliStore.new("localhost", "server-downstairs.localnetwork:8229")
|
16
|
-
#
|
17
|
-
# If no addresses are specified, then DalliStore will connect to
|
18
|
-
# localhost port 11211 (the default memcached port).
|
19
|
-
#
|
20
|
-
def initialize(*addresses)
|
21
|
-
addresses = addresses.flatten
|
22
|
-
options = addresses.extract_options!
|
23
|
-
options[:compression] = options.delete(:compress) || options[:compression]
|
24
|
-
addresses << 'localhost:11211' if addresses.empty?
|
25
|
-
@data = Dalli::Client.new(addresses, options)
|
26
|
-
end
|
27
|
-
|
28
|
-
def fetch(name, options={})
|
29
|
-
if block_given?
|
30
|
-
unless options[:force]
|
31
|
-
entry = instrument(:read, name, options) do |payload|
|
32
|
-
payload[:super_operation] = :fetch if payload
|
33
|
-
read_entry(name, options)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
if entry
|
38
|
-
instrument(:fetch_hit, name, options) { |payload| }
|
39
|
-
entry
|
40
|
-
else
|
41
|
-
result = instrument(:generate, name, options) do |payload|
|
42
|
-
yield
|
43
|
-
end
|
44
|
-
write(name, result, options)
|
45
|
-
result
|
46
|
-
end
|
47
|
-
else
|
48
|
-
read(name, options)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def read(name, options={})
|
53
|
-
instrument(:read, name, options) do |payload|
|
54
|
-
entry = read_entry(name, options)
|
55
|
-
payload[:hit] = !!entry if payload
|
56
|
-
entry
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def write(name, value, options={})
|
61
|
-
instrument(:write, name, options) do |payload|
|
62
|
-
write_entry(name, value, options)
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def exist?(name, options={})
|
67
|
-
!!read_entry(name, options)
|
68
|
-
end
|
69
|
-
|
70
|
-
def delete(name, options={})
|
71
|
-
@data.delete(name)
|
72
|
-
end
|
73
|
-
|
74
|
-
# Reads multiple keys from the cache using a single call to the
|
75
|
-
# servers for all keys. Keys must be Strings.
|
76
|
-
def read_multi(*names)
|
77
|
-
names.extract_options!
|
78
|
-
names = names.flatten
|
79
|
-
|
80
|
-
mapping = names.inject({}) { |memo, name| memo[escape(name)] = name; memo }
|
81
|
-
instrument(:read_multi, names) do
|
82
|
-
results = @data.get_multi(mapping.keys)
|
83
|
-
results.inject({}) do |memo, (inner, value)|
|
84
|
-
entry = results[inner]
|
85
|
-
# NB Backwards data compatibility, to be removed at some point
|
86
|
-
memo[mapping[inner]] = (entry.is_a?(ActiveSupport::Cache::Entry) ? entry.value : entry)
|
87
|
-
memo
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# Increment a cached value. This method uses the memcached incr atomic
|
93
|
-
# operator and can only be used on values written with the :raw option.
|
94
|
-
# Calling it on a value not stored with :raw will fail.
|
95
|
-
# :initial defaults to the amount passed in, as if the counter was initially zero.
|
96
|
-
# memcached counters cannot hold negative values.
|
97
|
-
def increment(name, amount = 1, options={}) # :nodoc:
|
98
|
-
initial = options[:initial] || amount
|
99
|
-
expires_in = options[:expires_in]
|
100
|
-
instrument(:increment, name, :amount => amount) do
|
101
|
-
@data.incr(name, amount, expires_in, initial)
|
102
|
-
end
|
103
|
-
rescue Dalli::DalliError => e
|
104
|
-
logger.error("DalliError: #{e.message}") if logger
|
105
|
-
nil
|
106
|
-
end
|
107
|
-
|
108
|
-
# Decrement a cached value. This method uses the memcached decr atomic
|
109
|
-
# operator and can only be used on values written with the :raw option.
|
110
|
-
# Calling it on a value not stored with :raw will fail.
|
111
|
-
# :initial defaults to zero, as if the counter was initially zero.
|
112
|
-
# memcached counters cannot hold negative values.
|
113
|
-
def decrement(name, amount = 1, options={}) # :nodoc:
|
114
|
-
initial = options[:initial] || 0
|
115
|
-
expires_in = options[:expires_in]
|
116
|
-
instrument(:decrement, name, :amount => amount) do
|
117
|
-
@data.decr(name, amount, expires_in, initial)
|
118
|
-
end
|
119
|
-
rescue Dalli::DalliError => e
|
120
|
-
logger.error("DalliError: #{e.message}") if logger
|
121
|
-
nil
|
122
|
-
end
|
123
|
-
|
124
|
-
# Clear the entire cache on all memcached servers. This method should
|
125
|
-
# be used with care when using a shared cache.
|
126
|
-
def clear(options=nil)
|
127
|
-
@data.flush_all
|
128
|
-
end
|
129
|
-
|
130
|
-
# Get the statistics from the memcached servers.
|
131
|
-
def stats
|
132
|
-
@data.stats
|
133
|
-
end
|
134
|
-
|
135
|
-
def reset
|
136
|
-
@data.reset
|
137
|
-
end
|
138
|
-
|
139
|
-
protected
|
140
|
-
|
141
|
-
# Read an entry from the cache.
|
142
|
-
def read_entry(key, options) # :nodoc:
|
143
|
-
entry = @data.get(escape(key), options)
|
144
|
-
# NB Backwards data compatibility, to be removed at some point
|
145
|
-
entry.is_a?(ActiveSupport::Cache::Entry) ? entry.value : entry
|
146
|
-
rescue Dalli::DalliError => e
|
147
|
-
logger.error("DalliError: #{e.message}") if logger
|
148
|
-
nil
|
149
|
-
end
|
150
|
-
|
151
|
-
# Write an entry to the cache.
|
152
|
-
def write_entry(key, value, options) # :nodoc:
|
153
|
-
options ||= {}
|
154
|
-
method = options[:unless_exist] ? :add : :set
|
155
|
-
expires_in = options[:expires_in]
|
156
|
-
@data.send(method, escape(key), value, expires_in, options)
|
157
|
-
rescue Dalli::DalliError => e
|
158
|
-
logger.error("DalliError: #{e.message}") if logger
|
159
|
-
false
|
160
|
-
end
|
161
|
-
|
162
|
-
# Delete an entry from the cache.
|
163
|
-
def delete_entry(key, options) # :nodoc:
|
164
|
-
@data.delete(escape(key))
|
165
|
-
rescue Dalli::DalliError => e
|
166
|
-
logger.error("DalliError: #{e.message}") if logger
|
167
|
-
false
|
168
|
-
end
|
169
|
-
|
170
|
-
private
|
171
|
-
|
172
|
-
def escape(key)
|
173
|
-
key = key.to_s.dup
|
174
|
-
key = key.force_encoding("BINARY") if key.encoding_aware?
|
175
|
-
key = key.gsub(ESCAPE_KEY_CHARS){ |match| "%#{match.getbyte(0).to_s(16).upcase}" }
|
176
|
-
key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
|
177
|
-
key
|
178
|
-
end
|
179
|
-
|
180
|
-
def instrument(operation, key, options = nil)
|
181
|
-
log(operation, key, options)
|
182
|
-
|
183
|
-
if ActiveSupport::Cache::Store.instrument
|
184
|
-
payload = { :key => key }
|
185
|
-
payload.merge!(options) if options.is_a?(Hash)
|
186
|
-
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) }
|
187
|
-
else
|
188
|
-
yield(nil)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def log(operation, key, options = nil)
|
193
|
-
return unless logger && logger.debug?
|
194
|
-
logger.debug("Cache #{operation}: #{key}#{options.blank? ? "" : " (#{options.inspect})"}")
|
195
|
-
end
|
196
|
-
|
197
|
-
def logger
|
198
|
-
Dalli.logger
|
199
|
-
end
|
200
|
-
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
data/test/abstract_unit.rb
DELETED
@@ -1,281 +0,0 @@
|
|
1
|
-
# Used to test the full Rails stack.
|
2
|
-
# Stolen from the Rails 3.0 source.
|
3
|
-
# Needed for the session store tests.
|
4
|
-
require 'active_support/core_ext/kernel/reporting'
|
5
|
-
require 'active_support/core_ext/string/encoding'
|
6
|
-
if "ruby".encoding_aware?
|
7
|
-
# These are the normal settings that will be set up by Railties
|
8
|
-
# TODO: Have these tests support other combinations of these values
|
9
|
-
silence_warnings do
|
10
|
-
Encoding.default_internal = "UTF-8"
|
11
|
-
Encoding.default_external = "UTF-8"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
require 'test/unit'
|
16
|
-
require 'abstract_controller'
|
17
|
-
require 'action_controller'
|
18
|
-
require 'action_view'
|
19
|
-
require 'action_dispatch'
|
20
|
-
require 'active_support/dependencies'
|
21
|
-
require 'action_controller/caching'
|
22
|
-
require 'action_controller/caching/sweeping'
|
23
|
-
|
24
|
-
require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late
|
25
|
-
|
26
|
-
module Rails
|
27
|
-
def self.logger
|
28
|
-
@logger ||= begin
|
29
|
-
l = Logger.new(STDOUT)
|
30
|
-
l.level = Logger::INFO; l
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Monkey patch the old routes initialization to be silenced.
|
36
|
-
class ActionDispatch::Routing::DeprecatedMapper
|
37
|
-
def initialize_with_silencer(*args)
|
38
|
-
ActiveSupport::Deprecation.silence { initialize_without_silencer(*args) }
|
39
|
-
end
|
40
|
-
alias_method_chain :initialize, :silencer
|
41
|
-
end
|
42
|
-
|
43
|
-
ActiveSupport::Dependencies.hook!
|
44
|
-
|
45
|
-
# Show backtraces for deprecated behavior for quicker cleanup.
|
46
|
-
ActiveSupport::Deprecation.debug = true
|
47
|
-
|
48
|
-
ORIGINAL_LOCALES = I18n.available_locales.map {|locale| locale.to_s }.sort
|
49
|
-
|
50
|
-
module RackTestUtils
|
51
|
-
def body_to_string(body)
|
52
|
-
if body.respond_to?(:each)
|
53
|
-
str = ""
|
54
|
-
body.each {|s| str << s }
|
55
|
-
str
|
56
|
-
else
|
57
|
-
body
|
58
|
-
end
|
59
|
-
end
|
60
|
-
extend self
|
61
|
-
end
|
62
|
-
|
63
|
-
module SetupOnce
|
64
|
-
extend ActiveSupport::Concern
|
65
|
-
|
66
|
-
included do
|
67
|
-
cattr_accessor :setup_once_block
|
68
|
-
self.setup_once_block = nil
|
69
|
-
|
70
|
-
setup :run_setup_once
|
71
|
-
end
|
72
|
-
|
73
|
-
module ClassMethods
|
74
|
-
def setup_once(&block)
|
75
|
-
self.setup_once_block = block
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
private
|
80
|
-
def run_setup_once
|
81
|
-
if self.setup_once_block
|
82
|
-
self.setup_once_block.call
|
83
|
-
self.setup_once_block = nil
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
|
89
|
-
|
90
|
-
module ActiveSupport
|
91
|
-
class TestCase
|
92
|
-
include SetupOnce
|
93
|
-
# Hold off drawing routes until all the possible controller classes
|
94
|
-
# have been loaded.
|
95
|
-
setup_once do
|
96
|
-
SharedTestRoutes.draw do
|
97
|
-
match ':controller(/:action(/:id))'
|
98
|
-
end
|
99
|
-
|
100
|
-
ActionController::IntegrationTest.app.routes.draw do
|
101
|
-
match ':controller(/:action(/:id))'
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
class RoutedRackApp
|
108
|
-
attr_reader :routes
|
109
|
-
|
110
|
-
def initialize(routes, &blk)
|
111
|
-
@routes = routes
|
112
|
-
@stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
|
113
|
-
end
|
114
|
-
|
115
|
-
def call(env)
|
116
|
-
@stack.call(env)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
class BasicController
|
121
|
-
attr_accessor :request
|
122
|
-
|
123
|
-
def config
|
124
|
-
@config ||= ActiveSupport::InheritableOptions.new(ActionController::Base.config).tap do |config|
|
125
|
-
# VIEW TODO: View tests should not require a controller
|
126
|
-
public_dir = File.expand_path("../fixtures/public", __FILE__)
|
127
|
-
config.assets_dir = public_dir
|
128
|
-
config.javascripts_dir = "#{public_dir}/javascripts"
|
129
|
-
config.stylesheets_dir = "#{public_dir}/stylesheets"
|
130
|
-
config
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
|
136
|
-
setup do
|
137
|
-
@routes = SharedTestRoutes
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
class ActionController::IntegrationTest < ActiveSupport::TestCase
|
142
|
-
def self.build_app(routes = nil)
|
143
|
-
RoutedRackApp.new(routes || ActionDispatch::Routing::RouteSet.new) do |middleware|
|
144
|
-
middleware.use "ActionDispatch::Callbacks"
|
145
|
-
middleware.use "ActionDispatch::ParamsParser"
|
146
|
-
middleware.use "ActionDispatch::Cookies"
|
147
|
-
middleware.use "ActionDispatch::Flash"
|
148
|
-
middleware.use "ActionDispatch::Head"
|
149
|
-
yield(middleware) if block_given?
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
self.app = build_app
|
154
|
-
|
155
|
-
# Stub Rails dispatcher so it does not get controller references and
|
156
|
-
# simply return the controller#action as Rack::Body.
|
157
|
-
class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
|
158
|
-
protected
|
159
|
-
def controller_reference(controller_param)
|
160
|
-
controller_param
|
161
|
-
end
|
162
|
-
|
163
|
-
def dispatch(controller, action, env)
|
164
|
-
[200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def self.stub_controllers
|
169
|
-
old_dispatcher = ActionDispatch::Routing::RouteSet::Dispatcher
|
170
|
-
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
|
171
|
-
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, StubDispatcher }
|
172
|
-
yield ActionDispatch::Routing::RouteSet.new
|
173
|
-
ensure
|
174
|
-
ActionDispatch::Routing::RouteSet.module_eval { remove_const :Dispatcher }
|
175
|
-
ActionDispatch::Routing::RouteSet.module_eval { const_set :Dispatcher, old_dispatcher }
|
176
|
-
end
|
177
|
-
|
178
|
-
def with_routing(&block)
|
179
|
-
temporary_routes = ActionDispatch::Routing::RouteSet.new
|
180
|
-
old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
|
181
|
-
old_routes = SharedTestRoutes
|
182
|
-
silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
|
183
|
-
|
184
|
-
yield temporary_routes
|
185
|
-
ensure
|
186
|
-
self.class.app = old_app
|
187
|
-
silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
|
188
|
-
end
|
189
|
-
|
190
|
-
def with_autoload_path(path)
|
191
|
-
path = File.join(File.dirname(__FILE__), "fixtures", path)
|
192
|
-
if ActiveSupport::Dependencies.autoload_paths.include?(path)
|
193
|
-
yield
|
194
|
-
else
|
195
|
-
begin
|
196
|
-
ActiveSupport::Dependencies.autoload_paths << path
|
197
|
-
yield
|
198
|
-
ensure
|
199
|
-
ActiveSupport::Dependencies.autoload_paths.reject! {|p| p == path}
|
200
|
-
ActiveSupport::Dependencies.clear
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Temporary base class
|
207
|
-
class Rack::TestCase < ActionController::IntegrationTest
|
208
|
-
def self.testing(klass = nil)
|
209
|
-
if klass
|
210
|
-
@testing = "/#{klass.name.underscore}".sub!(/_controller$/, '')
|
211
|
-
else
|
212
|
-
@testing
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def get(thing, *args)
|
217
|
-
if thing.is_a?(Symbol)
|
218
|
-
super("#{self.class.testing}/#{thing}", *args)
|
219
|
-
else
|
220
|
-
super
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
def assert_body(body)
|
225
|
-
assert_equal body, Array.wrap(response.body).join
|
226
|
-
end
|
227
|
-
|
228
|
-
def assert_status(code)
|
229
|
-
assert_equal code, response.status
|
230
|
-
end
|
231
|
-
|
232
|
-
def assert_response(body, status = 200, headers = {})
|
233
|
-
assert_body body
|
234
|
-
assert_status status
|
235
|
-
headers.each do |header, value|
|
236
|
-
assert_header header, value
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def assert_content_type(type)
|
241
|
-
assert_equal type, response.headers["Content-Type"]
|
242
|
-
end
|
243
|
-
|
244
|
-
def assert_header(name, value)
|
245
|
-
assert_equal value, response.headers[name]
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
class ActionController::Base
|
250
|
-
def self.test_routes(&block)
|
251
|
-
routes = ActionDispatch::Routing::RouteSet.new
|
252
|
-
routes.draw(&block)
|
253
|
-
include routes.url_helpers
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
class ::ApplicationController < ActionController::Base
|
258
|
-
end
|
259
|
-
|
260
|
-
module ActionController
|
261
|
-
class Base
|
262
|
-
include ActionController::Testing
|
263
|
-
end
|
264
|
-
|
265
|
-
Base.view_paths = []
|
266
|
-
|
267
|
-
class TestCase
|
268
|
-
include ActionDispatch::TestProcess
|
269
|
-
|
270
|
-
setup do
|
271
|
-
@routes = SharedTestRoutes
|
272
|
-
end
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
|
-
# This stub emulates the Railtie including the URL helpers from a Rails application
|
277
|
-
module ActionController
|
278
|
-
class Base
|
279
|
-
include SharedTestRoutes.url_helpers
|
280
|
-
end
|
281
|
-
end
|
data/test/benchmark_test.rb
DELETED
@@ -1,187 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'benchmark'
|
3
|
-
require 'active_support/cache/dalli_store'
|
4
|
-
|
5
|
-
describe 'performance' do
|
6
|
-
before do
|
7
|
-
puts "Testing #{Dalli::VERSION} with #{RUBY_DESCRIPTION}"
|
8
|
-
# We'll use a simple @value to try to avoid spending time in Marshal,
|
9
|
-
# which is a constant penalty that both clients have to pay
|
10
|
-
@value = []
|
11
|
-
@marshalled = Marshal.dump(@value)
|
12
|
-
|
13
|
-
@servers = ['127.0.0.1:19122', 'localhost:19122']
|
14
|
-
@key1 = "Short"
|
15
|
-
@key2 = "Sym1-2-3::45"*8
|
16
|
-
@key3 = "Long"*40
|
17
|
-
@key4 = "Medium"*8
|
18
|
-
# 5 and 6 are only used for multiget miss test
|
19
|
-
@key5 = "Medium2"*8
|
20
|
-
@key6 = "Long3"*40
|
21
|
-
@counter = 'counter'
|
22
|
-
end
|
23
|
-
|
24
|
-
should 'run benchmarks' do
|
25
|
-
memcached do
|
26
|
-
|
27
|
-
Benchmark.bm(31) do |x|
|
28
|
-
|
29
|
-
n = 2500
|
30
|
-
|
31
|
-
@ds = ActiveSupport::Cache::DalliStore.new(@servers)
|
32
|
-
x.report("mixed:rails:dalli") do
|
33
|
-
n.times do
|
34
|
-
@ds.read @key1
|
35
|
-
@ds.write @key2, @value
|
36
|
-
@ds.fetch(@key3) { @value }
|
37
|
-
@ds.fetch(@key2) { @value }
|
38
|
-
@ds.fetch(@key1) { @value }
|
39
|
-
@ds.write @key2, @value, :unless_exists => true
|
40
|
-
@ds.delete @key2
|
41
|
-
@ds.increment @counter, 1, :initial => 100
|
42
|
-
@ds.increment @counter, 1, :expires_in => 12
|
43
|
-
@ds.decrement @counter, 1
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
@m = Dalli::Client.new(@servers)
|
48
|
-
x.report("set:plain:dalli") do
|
49
|
-
n.times do
|
50
|
-
@m.set @key1, @marshalled, 0, :raw => true
|
51
|
-
@m.set @key2, @marshalled, 0, :raw => true
|
52
|
-
@m.set @key3, @marshalled, 0, :raw => true
|
53
|
-
@m.set @key1, @marshalled, 0, :raw => true
|
54
|
-
@m.set @key2, @marshalled, 0, :raw => true
|
55
|
-
@m.set @key3, @marshalled, 0, :raw => true
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
@m = Dalli::Client.new(@servers)
|
60
|
-
x.report("setq:plain:dalli") do
|
61
|
-
@m.multi do
|
62
|
-
n.times do
|
63
|
-
@m.set @key1, @marshalled, 0, :raw => true
|
64
|
-
@m.set @key2, @marshalled, 0, :raw => true
|
65
|
-
@m.set @key3, @marshalled, 0, :raw => true
|
66
|
-
@m.set @key1, @marshalled, 0, :raw => true
|
67
|
-
@m.set @key2, @marshalled, 0, :raw => true
|
68
|
-
@m.set @key3, @marshalled, 0, :raw => true
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
@m = Dalli::Client.new(@servers)
|
74
|
-
x.report("set:ruby:dalli") do
|
75
|
-
n.times do
|
76
|
-
@m.set @key1, @value
|
77
|
-
@m.set @key2, @value
|
78
|
-
@m.set @key3, @value
|
79
|
-
@m.set @key1, @value
|
80
|
-
@m.set @key2, @value
|
81
|
-
@m.set @key3, @value
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
@m = Dalli::Client.new(@servers)
|
86
|
-
x.report("get:plain:dalli") do
|
87
|
-
n.times do
|
88
|
-
@m.get @key1, :raw => true
|
89
|
-
@m.get @key2, :raw => true
|
90
|
-
@m.get @key3, :raw => true
|
91
|
-
@m.get @key1, :raw => true
|
92
|
-
@m.get @key2, :raw => true
|
93
|
-
@m.get @key3, :raw => true
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
@m = Dalli::Client.new(@servers)
|
98
|
-
x.report("get:ruby:dalli") do
|
99
|
-
n.times do
|
100
|
-
@m.get @key1
|
101
|
-
@m.get @key2
|
102
|
-
@m.get @key3
|
103
|
-
@m.get @key1
|
104
|
-
@m.get @key2
|
105
|
-
@m.get @key3
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
@m = Dalli::Client.new(@servers)
|
110
|
-
x.report("multiget:ruby:dalli") do
|
111
|
-
n.times do
|
112
|
-
# We don't use the keys array because splat is slow
|
113
|
-
@m.get_multi @key1, @key2, @key3, @key4, @key5, @key6
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
@m = Dalli::Client.new(@servers)
|
118
|
-
x.report("missing:ruby:dalli") do
|
119
|
-
n.times do
|
120
|
-
begin @m.delete @key1; rescue; end
|
121
|
-
begin @m.get @key1; rescue; end
|
122
|
-
begin @m.delete @key2; rescue; end
|
123
|
-
begin @m.get @key2; rescue; end
|
124
|
-
begin @m.delete @key3; rescue; end
|
125
|
-
begin @m.get @key3; rescue; end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
@m = Dalli::Client.new(@servers)
|
130
|
-
x.report("mixed:ruby:dalli") do
|
131
|
-
n.times do
|
132
|
-
@m.set @key1, @value
|
133
|
-
@m.set @key2, @value
|
134
|
-
@m.set @key3, @value
|
135
|
-
@m.get @key1
|
136
|
-
@m.get @key2
|
137
|
-
@m.get @key3
|
138
|
-
@m.set @key1, @value
|
139
|
-
@m.get @key1
|
140
|
-
@m.set @key2, @value
|
141
|
-
@m.get @key2
|
142
|
-
@m.set @key3, @value
|
143
|
-
@m.get @key3
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
@m = Dalli::Client.new(@servers)
|
148
|
-
x.report("mixedq:ruby:dalli") do
|
149
|
-
@m.multi do
|
150
|
-
n.times do
|
151
|
-
@m.set @key1, @value
|
152
|
-
@m.set @key2, @value
|
153
|
-
@m.set @key3, @value
|
154
|
-
@m.get @key1
|
155
|
-
@m.get @key2
|
156
|
-
@m.get @key3
|
157
|
-
@m.set @key1, @value
|
158
|
-
@m.get @key1
|
159
|
-
@m.set @key2, @value
|
160
|
-
@m.replace @key2, @value
|
161
|
-
@m.delete @key3
|
162
|
-
@m.add @key3, @value
|
163
|
-
@m.get @key2
|
164
|
-
@m.set @key3, @value
|
165
|
-
@m.get @key3
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
@m = Dalli::Client.new(@servers)
|
171
|
-
x.report("incr:ruby:dalli") do
|
172
|
-
counter = 'foocount'
|
173
|
-
n.times do
|
174
|
-
@m.incr counter, 1, 0, 1
|
175
|
-
end
|
176
|
-
n.times do
|
177
|
-
@m.decr counter, 1
|
178
|
-
end
|
179
|
-
|
180
|
-
assert_equal 0, @m.incr(counter, 0)
|
181
|
-
end
|
182
|
-
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
end
|
data/test/helper.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
$TESTING = true
|
2
|
-
require 'rubygems'
|
3
|
-
# require 'simplecov'
|
4
|
-
# SimpleCov.start
|
5
|
-
WANT_RAILS_VERSION = ENV['RAILS_VERSION'] || '>= 3.0.0'
|
6
|
-
gem 'rails', WANT_RAILS_VERSION
|
7
|
-
require 'rails'
|
8
|
-
puts "Testing with Rails #{Rails.version}"
|
9
|
-
|
10
|
-
require 'mini_shoulda'
|
11
|
-
require 'minitest/pride'
|
12
|
-
require 'minitest/autorun'
|
13
|
-
require 'memcached_mock'
|
14
|
-
require 'mocha'
|
15
|
-
|
16
|
-
require 'dalli'
|
17
|
-
require 'logger'
|
18
|
-
|
19
|
-
Dalli.logger = Logger.new(STDOUT)
|
20
|
-
Dalli.logger.level = Logger::ERROR
|
21
|
-
|
22
|
-
class MiniTest::Spec
|
23
|
-
include MemcachedMock::Helper
|
24
|
-
|
25
|
-
def assert_error(error, regexp=nil, &block)
|
26
|
-
ex = assert_raises(error, &block)
|
27
|
-
assert_match(regexp, ex.message, "#{ex.class.name}: #{ex.message}\n#{ex.backtrace.join("\n\t")}")
|
28
|
-
end
|
29
|
-
|
30
|
-
def with_activesupport
|
31
|
-
require 'active_support/all'
|
32
|
-
require 'active_support/cache/dalli_store'
|
33
|
-
yield
|
34
|
-
end
|
35
|
-
|
36
|
-
def with_actionpack
|
37
|
-
require 'action_dispatch'
|
38
|
-
require 'action_controller'
|
39
|
-
yield
|
40
|
-
end
|
41
|
-
end
|