moneta 0.7.4 → 0.7.5
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/.gitignore +1 -2
- data/.travis.yml +20 -13
- data/CHANGES +5 -0
- data/Gemfile +24 -25
- data/LICENSE +1 -1
- data/README.md +32 -16
- data/Rakefile +36 -6
- data/lib/moneta/builder.rb +20 -6
- data/lib/moneta/mixins.rb +11 -4
- data/lib/moneta/version.rb +1 -1
- data/script/benchmarks +378 -0
- data/script/{generate-specs.rb → generate-specs} +92 -83
- data/script/install-bundle +26 -0
- data/script/kill-travis +16 -0
- data/script/start-services +8 -0
- data/script/upload-bundle +2 -0
- data/spec/helper.rb +9 -3
- data/spec/moneta/adapter_activerecord_spec.rb +1 -1
- data/spec/moneta/adapter_cassandra_spec.rb +1 -1
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +2 -2
- data/spec/moneta/adapter_client_spec.rb +1 -1
- data/spec/moneta/adapter_cookie_spec.rb +2 -2
- data/spec/moneta/adapter_couch_spec.rb +1 -1
- data/spec/moneta/adapter_datamapper_spec.rb +1 -1
- data/spec/moneta/adapter_daybreak_spec.rb +2 -2
- data/spec/moneta/adapter_dbm_spec.rb +1 -1
- data/spec/moneta/adapter_file_spec.rb +1 -1
- data/spec/moneta/adapter_fog_spec.rb +2 -2
- data/spec/moneta/adapter_gdbm_spec.rb +1 -1
- data/spec/moneta/adapter_hbase_spec.rb +1 -1
- data/spec/moneta/adapter_leveldb_spec.rb +1 -1
- data/spec/moneta/adapter_localmemcache_spec.rb +1 -1
- data/spec/moneta/adapter_lruhash_spec.rb +2 -2
- data/spec/moneta/adapter_memcached_dalli_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_native_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +1 -1
- data/spec/moneta/adapter_memory_spec.rb +19 -1
- data/spec/moneta/adapter_mongo_spec.rb +2 -2
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +1 -1
- data/spec/moneta/adapter_pstore_spec.rb +1 -1
- data/spec/moneta/adapter_redis_spec.rb +1 -1
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +1 -1
- data/spec/moneta/adapter_restclient_spec.rb +1 -1
- data/spec/moneta/adapter_riak_spec.rb +1 -1
- data/spec/moneta/adapter_sdbm_spec.rb +1 -1
- data/spec/moneta/adapter_sequel_spec.rb +1 -1
- data/spec/moneta/adapter_sqlite_spec.rb +1 -1
- data/spec/moneta/adapter_tdb_spec.rb +1 -1
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -1
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -1
- data/spec/moneta/adapter_yaml_spec.rb +1 -1
- data/spec/moneta/cache_file_memory_spec.rb +2 -2
- data/spec/moneta/cache_memory_null_spec.rb +2 -2
- data/spec/moneta/expires_file_spec.rb +1 -1
- data/spec/moneta/expires_memory_spec.rb +19 -19
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +19 -19
- data/spec/moneta/lock_spec.rb +19 -1
- data/spec/moneta/null_adapter_spec.rb +1 -1
- data/spec/moneta/optionmerger_spec.rb +14 -1
- data/spec/moneta/pool_spec.rb +1 -1
- data/spec/moneta/proxy_expires_memory_spec.rb +19 -1
- data/spec/moneta/proxy_redis_spec.rb +1 -1
- data/spec/moneta/shared_spec.rb +3 -3
- data/spec/moneta/simple_activerecord_spec.rb +1 -1
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_cassandra_spec.rb +1 -1
- data/spec/moneta/simple_client_tcp_spec.rb +1 -1
- data/spec/moneta/simple_client_unix_spec.rb +1 -1
- data/spec/moneta/simple_couch_spec.rb +1 -1
- data/spec/moneta/simple_couch_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -1
- data/spec/moneta/simple_daybreak_spec.rb +1 -1
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_dbm_spec.rb +1 -1
- data/spec/moneta/simple_dbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_file_spec.rb +1 -1
- data/spec/moneta/simple_file_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_fog_spec.rb +1 -1
- data/spec/moneta/simple_fog_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_gdbm_spec.rb +1 -1
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_spec.rb +1 -1
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_hbase_spec.rb +1 -1
- data/spec/moneta/simple_hbase_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_spec.rb +1 -1
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_spec.rb +1 -1
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_spec.rb +1 -1
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memcached_dalli_spec.rb +1 -1
- data/spec/moneta/simple_memcached_native_spec.rb +1 -1
- data/spec/moneta/simple_memcached_spec.rb +1 -1
- data/spec/moneta/simple_memory_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_compress_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -1
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -1
- data/spec/moneta/simple_mongo_spec.rb +1 -1
- data/spec/moneta/simple_null_spec.rb +1 -1
- data/spec/moneta/simple_pstore_spec.rb +1 -1
- data/spec/moneta/simple_pstore_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_redis_spec.rb +1 -1
- data/spec/moneta/simple_restclient_spec.rb +1 -1
- data/spec/moneta/simple_riak_spec.rb +1 -1
- data/spec/moneta/simple_riak_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_spec.rb +1 -1
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sequel_spec.rb +1 -1
- data/spec/moneta/simple_sequel_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_spec.rb +1 -1
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_tdb_spec.rb +1 -1
- data/spec/moneta/simple_tdb_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_tokyocabinet_spec.rb +1 -1
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +1 -1
- data/spec/moneta/simple_yaml_spec.rb +1 -1
- data/spec/moneta/simple_yaml_with_expires_spec.rb +1 -1
- data/spec/moneta/stack_file_memory_spec.rb +2 -2
- data/spec/moneta/stack_memory_file_spec.rb +3 -3
- data/spec/moneta/transformer_bencode_spec.rb +1 -1
- data/spec/moneta/transformer_bert_spec.rb +1 -1
- data/spec/moneta/transformer_bson_spec.rb +1 -1
- data/spec/moneta/transformer_bzip2_spec.rb +1 -1
- data/spec/moneta/transformer_json_spec.rb +1 -1
- data/spec/moneta/transformer_key_marshal_spec.rb +19 -19
- data/spec/moneta/transformer_key_yaml_spec.rb +19 -19
- data/spec/moneta/transformer_lzma_spec.rb +1 -1
- data/spec/moneta/transformer_lzo_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_base64_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_escape_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -1
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -1
- data/spec/moneta/transformer_msgpack_spec.rb +1 -1
- data/spec/moneta/transformer_ox_spec.rb +1 -1
- data/spec/moneta/transformer_quicklz_spec.rb +1 -1
- data/spec/moneta/transformer_snappy_spec.rb +1 -1
- data/spec/moneta/transformer_tnet_spec.rb +1 -1
- data/spec/moneta/transformer_value_marshal_spec.rb +1 -1
- data/spec/moneta/transformer_value_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_yaml_spec.rb +1 -1
- data/spec/moneta/transformer_zlib_spec.rb +1 -1
- data/spec/monetaspecs.rb +655 -151
- metadata +8 -6
- data/benchmarks/run.rb +0 -327
- data/script/install-bundle.rb +0 -35
data/script/benchmarks
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
|
+
require 'benchmark'
|
|
5
|
+
require 'moneta'
|
|
6
|
+
require 'fileutils'
|
|
7
|
+
|
|
8
|
+
class String
|
|
9
|
+
def random(n)
|
|
10
|
+
(1..n).map { self[rand(size),1] }.join
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Array
|
|
15
|
+
def sum
|
|
16
|
+
inject(0, &:+)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def randomize
|
|
20
|
+
rest, result = dup, []
|
|
21
|
+
result << rest.slice!(rand(rest.size)) until result.size == size
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class MonetaBenchmarks
|
|
27
|
+
DIR = __FILE__ + '.tmp'
|
|
28
|
+
FileUtils.mkpath(DIR)
|
|
29
|
+
|
|
30
|
+
STORES = {
|
|
31
|
+
# SDBM is unstable
|
|
32
|
+
# :SDBM => { :file => "#{DIR}/sdbm" },
|
|
33
|
+
# YAML is so fucking slow
|
|
34
|
+
# :YAML => { :file => "#{DIR}/yaml" },
|
|
35
|
+
:ActiveRecord => { :connection => { :adapter => 'sqlite3', :database => ':memory:' } },
|
|
36
|
+
:Cassandra => {},
|
|
37
|
+
:Client => {},
|
|
38
|
+
:Couch => {},
|
|
39
|
+
:DBM => { :file => "#{DIR}/dbm" },
|
|
40
|
+
:DataMapper => { :setup => "sqlite3:#{DIR}/datamapper" },
|
|
41
|
+
:Daybreak => { :file => "#{DIR}/daybreak" },
|
|
42
|
+
:File => { :dir => "#{DIR}/file" },
|
|
43
|
+
:GDBM => { :file => "#{DIR}/gdbm" },
|
|
44
|
+
:HBase => {},
|
|
45
|
+
:HashFile => { :dir => "#{DIR}/hashfile" },
|
|
46
|
+
:LRUHash => {},
|
|
47
|
+
:LevelDB => { :dir => "#{DIR}/leveldb" },
|
|
48
|
+
:LocalMemCache => { :file => "#{DIR}/lmc" },
|
|
49
|
+
:MemcachedDalli => {},
|
|
50
|
+
:MemcachedNative => {},
|
|
51
|
+
:Memory => {},
|
|
52
|
+
:Mongo => {},
|
|
53
|
+
:PStore => { :file => "#{DIR}/pstore" },
|
|
54
|
+
:Redis => {},
|
|
55
|
+
:RestClient => { :url => 'http://localhost:8808/' },
|
|
56
|
+
:Riak => {},
|
|
57
|
+
:Sequel => { :db => 'sqlite:/' },
|
|
58
|
+
:Sqlite => { :file => ':memory:' },
|
|
59
|
+
:TDB => { :file => "#{DIR}/tdb" },
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
CONFIGS = {
|
|
63
|
+
:uniform_small => {
|
|
64
|
+
:runs => 3,
|
|
65
|
+
:keys => 1000,
|
|
66
|
+
:min_key_length => 1,
|
|
67
|
+
:max_key_length => 32,
|
|
68
|
+
:key_dist => :uniform,
|
|
69
|
+
:min_val_length => 0,
|
|
70
|
+
:max_val_length => 256,
|
|
71
|
+
:val_dist => :uniform
|
|
72
|
+
},
|
|
73
|
+
:uniform_medium => {
|
|
74
|
+
:runs => 3,
|
|
75
|
+
:keys => 100,
|
|
76
|
+
:min_key_length => 3,
|
|
77
|
+
:max_key_length => 200,
|
|
78
|
+
:key_dist => :uniform,
|
|
79
|
+
:min_val_length => 0,
|
|
80
|
+
:max_val_length => 1024,
|
|
81
|
+
:val_dist => :uniform
|
|
82
|
+
},
|
|
83
|
+
:uniform_large => {
|
|
84
|
+
:runs => 3,
|
|
85
|
+
:keys => 100,
|
|
86
|
+
:min_key_length => 3,
|
|
87
|
+
:max_key_length => 200,
|
|
88
|
+
:key_dist => :uniform,
|
|
89
|
+
:min_val_length => 0,
|
|
90
|
+
:max_val_length => 10240,
|
|
91
|
+
:val_dist => :uniform
|
|
92
|
+
},
|
|
93
|
+
:normal_small => {
|
|
94
|
+
:runs => 3,
|
|
95
|
+
:keys => 1000,
|
|
96
|
+
:min_key_length => 1,
|
|
97
|
+
:max_key_length => 32,
|
|
98
|
+
:key_dist => :normal,
|
|
99
|
+
:min_val_length => 0,
|
|
100
|
+
:max_val_length => 256,
|
|
101
|
+
:val_dist => :normal
|
|
102
|
+
},
|
|
103
|
+
:normal_medium => {
|
|
104
|
+
:runs => 3,
|
|
105
|
+
:keys => 100,
|
|
106
|
+
:min_key_length => 3,
|
|
107
|
+
:max_key_length => 200,
|
|
108
|
+
:key_dist => :normal,
|
|
109
|
+
:min_val_length => 0,
|
|
110
|
+
:max_val_length => 1024,
|
|
111
|
+
:val_dist => :normal
|
|
112
|
+
},
|
|
113
|
+
:normal_large => {
|
|
114
|
+
:runs => 3,
|
|
115
|
+
:keys => 100,
|
|
116
|
+
:min_key_length => 3,
|
|
117
|
+
:max_key_length => 200,
|
|
118
|
+
:key_dist => :normal,
|
|
119
|
+
:min_val_length => 0,
|
|
120
|
+
:max_val_length => 10240,
|
|
121
|
+
:val_dist => :normal
|
|
122
|
+
},
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
DICT = 'ABCDEFGHIJKLNOPQRSTUVWXYZabcdefghijklnopqrstuvwxyz123456789'.freeze
|
|
126
|
+
HEADER = "\n Minimum Maximum Total Average Ops/s"
|
|
127
|
+
SEPARATOR = '=' * 68
|
|
128
|
+
|
|
129
|
+
module Rand
|
|
130
|
+
extend self
|
|
131
|
+
|
|
132
|
+
def normal_rand(mean, stddev)
|
|
133
|
+
# Box-Muller transform
|
|
134
|
+
theta = 2 * Math::PI * (rand(1e10) / 1e10)
|
|
135
|
+
scale = stddev * Math.sqrt(-2 * Math.log(1 - (rand(1e10) / 1e10)))
|
|
136
|
+
[mean + scale * Math.cos(theta),
|
|
137
|
+
mean + scale * Math.sin(theta)]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def uniform(min, max)
|
|
141
|
+
rand(max - min) + min
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def normal(min, max)
|
|
145
|
+
mean = (min + max) / 2
|
|
146
|
+
stddev = (max - min) / 4
|
|
147
|
+
loop do
|
|
148
|
+
val = normal_rand(mean, stddev)
|
|
149
|
+
return val.first if val.first >= min && val.first <= max
|
|
150
|
+
return val.last if val.last >= min && val.last <= max
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def parallel(&block)
|
|
156
|
+
if defined?(JRUBY_VERSION)
|
|
157
|
+
Thread.new(&block)
|
|
158
|
+
else
|
|
159
|
+
Process.fork(&block)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def write_histogram(file, sizes)
|
|
164
|
+
min = sizes.min
|
|
165
|
+
delta = sizes.max - min
|
|
166
|
+
histogram = []
|
|
167
|
+
sizes.each do |s|
|
|
168
|
+
s = 10 * (s - min) / delta
|
|
169
|
+
histogram[s] ||= 0
|
|
170
|
+
histogram[s] += 1
|
|
171
|
+
end
|
|
172
|
+
File.open(file, 'w') do |f|
|
|
173
|
+
histogram.each_with_index { |n,i| f.puts "#{i*delta/10+min} #{n}" }
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def start_servers
|
|
178
|
+
parallel do
|
|
179
|
+
begin
|
|
180
|
+
Moneta::Server.new(Moneta.new(:Memory)).run
|
|
181
|
+
rescue Exception => ex
|
|
182
|
+
puts "\e[31mFailed to start Moneta server - #{ex.message}\e[0m"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
parallel do
|
|
187
|
+
begin
|
|
188
|
+
require 'rack'
|
|
189
|
+
require 'webrick'
|
|
190
|
+
require 'rack/moneta_rest'
|
|
191
|
+
|
|
192
|
+
# Keep webrick quiet
|
|
193
|
+
::WEBrick::HTTPServer.class_eval do
|
|
194
|
+
def access_log(config, req, res); end
|
|
195
|
+
end
|
|
196
|
+
::WEBrick::BasicLog.class_eval do
|
|
197
|
+
def log(level, data); end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
Rack::Server.start(:app => Rack::Builder.app do
|
|
201
|
+
use Rack::Lint
|
|
202
|
+
run Rack::MonetaRest.new(:store => :Memory)
|
|
203
|
+
end,
|
|
204
|
+
:environment => :none,
|
|
205
|
+
:server => :webrick,
|
|
206
|
+
:Port => 8808)
|
|
207
|
+
rescue Exception => ex
|
|
208
|
+
puts "\e[31mFailed to start Rack server - #{ex.message}\e[0m"
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
sleep 1 # Wait for servers
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def test_stores
|
|
216
|
+
STORES.each do |name, options|
|
|
217
|
+
begin
|
|
218
|
+
if name == :DataMapper
|
|
219
|
+
begin
|
|
220
|
+
require 'dm-core'
|
|
221
|
+
DataMapper.setup(:default, :adapter => :in_memory)
|
|
222
|
+
rescue LoadError => ex
|
|
223
|
+
puts "\e[31mFailed to load DataMapper - #{ex.message}\e[0m"
|
|
224
|
+
end
|
|
225
|
+
elsif name == :Riak
|
|
226
|
+
require 'riak'
|
|
227
|
+
Riak.disable_list_keys_warnings = true
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
cache = Moneta.new(name, options.dup)
|
|
231
|
+
cache['test'] = 'test'
|
|
232
|
+
rescue Exception => ex
|
|
233
|
+
puts "\e[31m#{name} not benchmarked - #{ex.message}\e[0m"
|
|
234
|
+
STORES.delete(name)
|
|
235
|
+
ensure
|
|
236
|
+
cache.close if cache
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def generate_data
|
|
242
|
+
until @data.size == @config[:keys]
|
|
243
|
+
key = DICT.random(Rand.send(@config[:key_dist], @config[:min_key_length], @config[:max_key_length]))
|
|
244
|
+
@data[key] = DICT.random(Rand.send(@config[:val_dist], @config[:min_val_length], @config[:max_val_length]))
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
key_lengths, val_lengths = @data.keys.map(&:size), @data.values.map(&:size)
|
|
248
|
+
@data = @data.to_a
|
|
249
|
+
|
|
250
|
+
write_histogram("#{DIR}/key.histogram", key_lengths)
|
|
251
|
+
write_histogram("#{DIR}/value.histogram", val_lengths)
|
|
252
|
+
|
|
253
|
+
puts "\n\e[1m\e[34m#{SEPARATOR}\n\e[34mComputing keys and values...\n\e[34m#{SEPARATOR}\e[0m"
|
|
254
|
+
puts %{ Minimum Maximum Total Average}
|
|
255
|
+
puts 'Key Length % 8d % 8d % 8d % 8d ' % [key_lengths.min, key_lengths.max, key_lengths.sum, key_lengths.sum / @data.size]
|
|
256
|
+
puts 'Value Length % 8d % 8d % 8d % 8d ' % [val_lengths.min, val_lengths.max, val_lengths.sum, val_lengths.sum / @data.size]
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def print_config
|
|
260
|
+
puts "\e[1m\e[36m#{SEPARATOR}\n\e[36mConfig #{@config_name}\n\e[36m#{SEPARATOR}\e[0m"
|
|
261
|
+
@config.each do |k,v|
|
|
262
|
+
puts '%-16s = %-10s' % [k,v]
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def print_store_stats(name)
|
|
267
|
+
puts HEADER
|
|
268
|
+
[:write, :read, :sum].each do |i|
|
|
269
|
+
total = @stats[name][i].sum
|
|
270
|
+
ops = (@config[:runs] * @data.size) / total
|
|
271
|
+
line = '%-17.17s %-5s % 8d % 8d % 8d % 8d % 8d' %
|
|
272
|
+
[name, i, @stats[name][i].min * 1000, @stats[name][i].max * 1000,
|
|
273
|
+
total * 1000, total * 1000 / @config[:runs], ops]
|
|
274
|
+
@summary << [-ops, line << "\n"] if i == :sum
|
|
275
|
+
puts line
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
errors = @stats[name][:error].sum
|
|
279
|
+
if errors > 0
|
|
280
|
+
puts "\e[31m%-23.23s % 8d % 8d % 8d % 8d\e[0m" %
|
|
281
|
+
['Read errors', @stats[name][:error].min, @stats[name][:error].max, errors, errors / @config[:runs]]
|
|
282
|
+
else
|
|
283
|
+
puts "\e[32mNo read errors"
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def benchmark_store(name, options)
|
|
288
|
+
puts "\n\e[1m\e[34m#{SEPARATOR}\n\e[34m#{name}\n\e[34m#{SEPARATOR}\e[0m"
|
|
289
|
+
|
|
290
|
+
store = Moneta.new(name, options.dup)
|
|
291
|
+
|
|
292
|
+
@stats[name] = {
|
|
293
|
+
:write => [],
|
|
294
|
+
:read => [],
|
|
295
|
+
:sum => [],
|
|
296
|
+
:error => []
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
%w(Rehearse Measure).each do |type|
|
|
300
|
+
state = ''
|
|
301
|
+
print "%s [%#{2 * @config[:runs]}s] " % [type, state]
|
|
302
|
+
|
|
303
|
+
@config[:runs].times do |run|
|
|
304
|
+
store.clear
|
|
305
|
+
print "%s[%-#{2 * @config[:runs]}s] " % ["\b" * (2 * @config[:runs] + 3), state << 'W']
|
|
306
|
+
|
|
307
|
+
@data = @data.randomize
|
|
308
|
+
m1 = Benchmark.measure do
|
|
309
|
+
@data.each {|k,v| store[k] = v }
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
print "%s[%-#{2 * @config[:runs]}s] " % ["\b" * (2 * @config[:runs] + 3), state << 'R']
|
|
313
|
+
|
|
314
|
+
@data = @data.randomize
|
|
315
|
+
error = 0
|
|
316
|
+
m2 = Benchmark.measure do
|
|
317
|
+
@data.each do |k, v|
|
|
318
|
+
error += 1 if v != store[k]
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
if type == 'Measure'
|
|
323
|
+
@stats[name][:write] << m1.real
|
|
324
|
+
@stats[name][:error] << error
|
|
325
|
+
@stats[name][:read] << m2.real
|
|
326
|
+
@stats[name][:sum] << (m1.real + m2.real)
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
print_store_stats(name)
|
|
332
|
+
rescue StandardError => ex
|
|
333
|
+
puts "\n\e[31mFailed to benchmark #{name} - #{ex.message}\e[0m\n"
|
|
334
|
+
ensure
|
|
335
|
+
store.close if store
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def run_benchmarks
|
|
339
|
+
STORES.each {|name, options| benchmark_store(name, options) }
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def print_summary
|
|
343
|
+
puts "\n\e[1m\e[36m#{SEPARATOR}\n\e[36mSummary #{@config_name}: #{@config[:runs]} runs, #{@data.size} keys\n\e[36m#{SEPARATOR}\e[0m#{HEADER}\n"
|
|
344
|
+
@summary.sort_by(&:first).each do |entry|
|
|
345
|
+
puts entry.last
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def initialize(args)
|
|
350
|
+
@config_name = args.size == 1 ? args.first.to_sym : :uniform_medium
|
|
351
|
+
unless @config = CONFIGS[@config_name]
|
|
352
|
+
puts "Configuration #{@config_name} not found"
|
|
353
|
+
exit
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
# Disable jruby stdout pollution by memcached
|
|
357
|
+
if defined?(JRUBY_VERSION)
|
|
358
|
+
require 'java'
|
|
359
|
+
properties = java.lang.System.getProperties();
|
|
360
|
+
properties.put('net.spy.log.LoggerImpl', 'net.spy.memcached.compat.log.SunLogger');
|
|
361
|
+
java.lang.System.setProperties(properties);
|
|
362
|
+
java.util.logging.Logger.getLogger('').setLevel(java.util.logging.Level::OFF)
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
@stats, @data, @summary = {}, {}, []
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def run
|
|
369
|
+
start_servers
|
|
370
|
+
test_stores
|
|
371
|
+
print_config
|
|
372
|
+
generate_data
|
|
373
|
+
run_benchmarks
|
|
374
|
+
print_summary
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
MonetaBenchmarks.new(ARGV).run
|
|
@@ -2,43 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
PATH = File.expand_path(File.join(__FILE__, '..', '..', 'spec'))
|
|
4
4
|
|
|
5
|
+
class Array
|
|
6
|
+
def without(*x)
|
|
7
|
+
a = dup
|
|
8
|
+
x.each {|y| a.delete(y) }
|
|
9
|
+
a
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def with(*x)
|
|
13
|
+
a = dup
|
|
14
|
+
x.each {|y| a << y }
|
|
15
|
+
a
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
5
19
|
class Specs
|
|
6
20
|
attr_reader :key, :value, :specs
|
|
7
21
|
|
|
8
|
-
def initialize(
|
|
9
|
-
@specs = specs
|
|
10
|
-
@key = key || %w(object string hash boolean nil integer)
|
|
11
|
-
@value = value || %w(object string hash boolean nil integer)
|
|
22
|
+
def initialize(options = {})
|
|
23
|
+
@specs = options.delete(:specs).to_a
|
|
24
|
+
@key = options.delete(:key) || %w(object string hash boolean nil integer)
|
|
25
|
+
@value = options.delete(:value) || %w(object string hash boolean nil integer)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def new(options)
|
|
29
|
+
Specs.new({:specs => specs, :key => key, :value => value}.merge(options))
|
|
12
30
|
end
|
|
13
31
|
|
|
14
32
|
def stringkeys_only
|
|
15
|
-
|
|
33
|
+
new(:key => %w(string))
|
|
16
34
|
end
|
|
17
35
|
|
|
18
36
|
def stringvalues_only
|
|
19
|
-
|
|
37
|
+
new(:value => %w(string))
|
|
20
38
|
end
|
|
21
39
|
|
|
22
40
|
def simplekeys_only
|
|
23
|
-
|
|
41
|
+
new(:key => %w(string hash integer))
|
|
24
42
|
end
|
|
25
43
|
|
|
26
44
|
def simplevalues_only
|
|
27
|
-
|
|
45
|
+
new(:value => %w(string hash integer))
|
|
28
46
|
end
|
|
29
47
|
|
|
30
48
|
def without_increment
|
|
31
|
-
|
|
32
|
-
a.delete(:increment)
|
|
33
|
-
a << :not_increment
|
|
34
|
-
Specs.new(a, key, value)
|
|
49
|
+
new(:specs => specs.without(:increment).with(:not_increment))
|
|
35
50
|
end
|
|
36
51
|
|
|
37
52
|
def without_persist
|
|
38
|
-
|
|
39
|
-
a.delete(:persist)
|
|
40
|
-
a << :not_persist
|
|
41
|
-
Specs.new(a, key, value)
|
|
53
|
+
new(:specs => specs.without(:persist).with(:not_persist))
|
|
42
54
|
end
|
|
43
55
|
|
|
44
56
|
def with_expires
|
|
@@ -48,66 +60,45 @@ class Specs
|
|
|
48
60
|
a << :transform_value_with_expires
|
|
49
61
|
end
|
|
50
62
|
a << :expires
|
|
51
|
-
|
|
63
|
+
new(:specs => a)
|
|
52
64
|
end
|
|
53
65
|
|
|
54
66
|
def with_native_expires
|
|
55
|
-
|
|
56
|
-
a << :expires
|
|
57
|
-
Specs.new(a, key, value)
|
|
67
|
+
new(:specs => specs.with(:expires))
|
|
58
68
|
end
|
|
59
69
|
|
|
60
70
|
def without_marshallable
|
|
61
|
-
|
|
62
|
-
a.delete(:marshallable_value)
|
|
63
|
-
a.delete(:marshallable_key)
|
|
64
|
-
Specs.new(a, key, value)
|
|
71
|
+
new(:specs => specs.without(:marshallable_value, :marshallable_key))
|
|
65
72
|
end
|
|
66
73
|
|
|
67
74
|
def without_transform
|
|
68
|
-
|
|
69
|
-
a.delete(:marshallable_value)
|
|
70
|
-
a.delete(:marshallable_key)
|
|
71
|
-
a.delete(:transform_value)
|
|
72
|
-
Specs.new(a, key, value)
|
|
75
|
+
new(:specs => specs.without(:marshallable_value, :marshallable_key, :transform_value))
|
|
73
76
|
end
|
|
74
77
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
a.delete(:returndifferent)
|
|
78
|
-
Specs.new(a, key, value)
|
|
78
|
+
def returnsame
|
|
79
|
+
new(:specs => specs.without(:returndifferent).with(:returnsame))
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
def without_marshallable_key
|
|
82
|
-
|
|
83
|
-
a.delete(:marshallable_key)
|
|
84
|
-
Specs.new(a, key, value)
|
|
83
|
+
new(:specs => specs.without(:marshallable_key))
|
|
85
84
|
end
|
|
86
85
|
|
|
87
86
|
def without_marshallable_value
|
|
88
|
-
|
|
89
|
-
a.delete(:marshallable_value)
|
|
90
|
-
Specs.new(a, key, value)
|
|
87
|
+
new(:specs => specs.without(:marshallable_value))
|
|
91
88
|
end
|
|
92
89
|
|
|
93
90
|
def without_store
|
|
94
|
-
|
|
95
|
-
a.delete(:store)
|
|
96
|
-
a.delete(:transform_value)
|
|
97
|
-
a.delete(:marshallable_value)
|
|
98
|
-
Specs.new(a, key, value)
|
|
91
|
+
new(:specs => specs.without(:store, :transform_value, :marshallable_value))
|
|
99
92
|
end
|
|
100
93
|
|
|
101
94
|
def with_default_expires
|
|
102
|
-
|
|
103
|
-
a << :default_expires
|
|
104
|
-
Specs.new(a, key, value)
|
|
95
|
+
new(:specs => specs.with(:default_expires))
|
|
105
96
|
end
|
|
106
97
|
end
|
|
107
98
|
|
|
108
|
-
ADAPTER_SPECS = Specs.new([:null, :store, :returndifferent, :increment, :persist], %w(string), %w(string))
|
|
109
|
-
STANDARD_SPECS = Specs.new([:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist])
|
|
110
|
-
TRANSFORMER_SPECS = Specs.new([:null, :store, :returndifferent, :transform_value, :increment])
|
|
99
|
+
ADAPTER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :increment, :persist], :key => %w(string), :value => %w(string))
|
|
100
|
+
STANDARD_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :marshallable_key, :marshallable_value, :transform_value, :increment, :persist])
|
|
101
|
+
TRANSFORMER_SPECS = Specs.new(:specs => [:null, :store, :returndifferent, :transform_value, :increment])
|
|
111
102
|
|
|
112
103
|
header = "# Generated by #{File.basename(__FILE__)}\n"
|
|
113
104
|
|
|
@@ -402,7 +393,7 @@ end
|
|
|
402
393
|
},
|
|
403
394
|
'null_adapter' => {
|
|
404
395
|
:build => 'Moneta::Adapters::Null.new',
|
|
405
|
-
:specs => Specs.new([:null, :not_increment, :not_persist])
|
|
396
|
+
:specs => Specs.new(:specs => [:null, :not_increment, :not_persist])
|
|
406
397
|
},
|
|
407
398
|
'simple_sequel' => {
|
|
408
399
|
:store => :Sequel,
|
|
@@ -478,14 +469,14 @@ end
|
|
|
478
469
|
use :Expires
|
|
479
470
|
adapter :Memory
|
|
480
471
|
end},
|
|
481
|
-
:specs => STANDARD_SPECS.without_transform.with_expires.without_persist
|
|
472
|
+
:specs => STANDARD_SPECS.without_transform.with_expires.without_persist.returnsame
|
|
482
473
|
},
|
|
483
474
|
'expires_memory_with_default_expires' => {
|
|
484
475
|
:build => %{Moneta.build do
|
|
485
476
|
use :Expires, :expires => 1
|
|
486
477
|
adapter :Memory
|
|
487
478
|
end},
|
|
488
|
-
:specs => STANDARD_SPECS.without_transform.with_expires.with_default_expires.without_persist
|
|
479
|
+
:specs => STANDARD_SPECS.without_transform.with_expires.with_default_expires.without_persist.returnsame
|
|
489
480
|
},
|
|
490
481
|
'expires_file' => {
|
|
491
482
|
:build => %{Moneta.build do
|
|
@@ -522,7 +513,7 @@ end},
|
|
|
522
513
|
use :Proxy
|
|
523
514
|
adapter :Memory
|
|
524
515
|
end},
|
|
525
|
-
:specs => STANDARD_SPECS.without_transform.with_expires.
|
|
516
|
+
:specs => STANDARD_SPECS.without_transform.with_expires.returnsame.without_persist
|
|
526
517
|
},
|
|
527
518
|
'cache_file_memory' => {
|
|
528
519
|
:build => %{Moneta.build do
|
|
@@ -531,7 +522,7 @@ end},
|
|
|
531
522
|
cache { adapter :Memory }
|
|
532
523
|
end
|
|
533
524
|
end},
|
|
534
|
-
:specs => ADAPTER_SPECS,
|
|
525
|
+
:specs => ADAPTER_SPECS.returnsame,
|
|
535
526
|
:tests => %{
|
|
536
527
|
it 'stores loaded values in cache' do
|
|
537
528
|
store.backend['foo'] = 'bar'
|
|
@@ -552,15 +543,15 @@ end
|
|
|
552
543
|
cache(Moneta::Adapters::Null.new)
|
|
553
544
|
end
|
|
554
545
|
end},
|
|
555
|
-
:specs => ADAPTER_SPECS.without_persist
|
|
546
|
+
:specs => ADAPTER_SPECS.without_persist.returnsame
|
|
556
547
|
},
|
|
557
548
|
'shared' => {
|
|
558
549
|
:build => %{Moneta.build do
|
|
559
550
|
use(:Shared, :port => 9001) do
|
|
560
|
-
adapter :
|
|
551
|
+
adapter :PStore, :file => File.join(make_tempdir, 'shared')
|
|
561
552
|
end
|
|
562
553
|
end},
|
|
563
|
-
:specs => ADAPTER_SPECS
|
|
554
|
+
:specs => ADAPTER_SPECS,
|
|
564
555
|
:tests => %{
|
|
565
556
|
it 'shares values' do
|
|
566
557
|
store['shared_key'] = 'shared_value'
|
|
@@ -576,7 +567,7 @@ end
|
|
|
576
567
|
use(:Stack) do
|
|
577
568
|
add(Moneta.new(:Null))
|
|
578
569
|
add(Moneta::Adapters::Null.new)
|
|
579
|
-
add { adapter :File, :dir => File.join(make_tempdir, "
|
|
570
|
+
add { adapter :File, :dir => File.join(make_tempdir, "stack_file_memory") }
|
|
580
571
|
add { adapter :Memory }
|
|
581
572
|
end
|
|
582
573
|
end},
|
|
@@ -588,17 +579,17 @@ end},
|
|
|
588
579
|
add(Moneta.new(:Null))
|
|
589
580
|
add(Moneta::Adapters::Null.new)
|
|
590
581
|
add { adapter :Memory }
|
|
591
|
-
add { adapter :File, :dir => File.join(make_tempdir, "
|
|
582
|
+
add { adapter :File, :dir => File.join(make_tempdir, "stack_memory_file") }
|
|
592
583
|
end
|
|
593
584
|
end},
|
|
594
|
-
:specs => STANDARD_SPECS.without_increment.without_transform.stringkeys_only.stringvalues_only
|
|
585
|
+
:specs => STANDARD_SPECS.without_increment.returnsame.without_transform.stringkeys_only.stringvalues_only
|
|
595
586
|
},
|
|
596
587
|
'lock' => {
|
|
597
588
|
:build => %{Moneta.build do
|
|
598
589
|
use :Lock
|
|
599
590
|
adapter :Memory
|
|
600
591
|
end},
|
|
601
|
-
:specs => STANDARD_SPECS.without_transform.
|
|
592
|
+
:specs => STANDARD_SPECS.without_transform.returnsame.without_persist
|
|
602
593
|
},
|
|
603
594
|
'pool' => {
|
|
604
595
|
:build => %{Moneta.build do
|
|
@@ -725,7 +716,7 @@ end},
|
|
|
725
716
|
use :Transformer, :key => :marshal
|
|
726
717
|
adapter :Memory
|
|
727
718
|
end},
|
|
728
|
-
:specs => TRANSFORMER_SPECS,
|
|
719
|
+
:specs => TRANSFORMER_SPECS.returnsame,
|
|
729
720
|
:load_value => 'value'
|
|
730
721
|
},
|
|
731
722
|
'transformer_value_marshal' => {
|
|
@@ -749,7 +740,7 @@ end},
|
|
|
749
740
|
use :Transformer, :key => :yaml
|
|
750
741
|
adapter :Memory
|
|
751
742
|
end},
|
|
752
|
-
:specs => TRANSFORMER_SPECS,
|
|
743
|
+
:specs => TRANSFORMER_SPECS.returnsame,
|
|
753
744
|
:load_value => 'value'
|
|
754
745
|
},
|
|
755
746
|
'transformer_value_yaml' => {
|
|
@@ -888,7 +879,7 @@ end
|
|
|
888
879
|
:specs => ADAPTER_SPECS.without_increment.with_native_expires
|
|
889
880
|
},
|
|
890
881
|
'adapter_cassandra_with_default_expires' => {
|
|
891
|
-
:build => %{Moneta::Adapters::Cassandra.new(:expires => 1)},
|
|
882
|
+
:build => %{Moneta::Adapters::Cassandra.new(:keyspace => 'adapter_cassandra_with_default_expires', :expires => 1)},
|
|
892
883
|
:specs => ADAPTER_SPECS.without_increment.with_native_expires.with_default_expires
|
|
893
884
|
},
|
|
894
885
|
'adapter_hbase' => {
|
|
@@ -897,7 +888,7 @@ end
|
|
|
897
888
|
},
|
|
898
889
|
'adapter_cookie' => {
|
|
899
890
|
:build => 'Moneta::Adapters::Cookie.new',
|
|
900
|
-
:specs => ADAPTER_SPECS.without_persist
|
|
891
|
+
:specs => ADAPTER_SPECS.without_persist.returnsame
|
|
901
892
|
},
|
|
902
893
|
'adapter_couch' => {
|
|
903
894
|
:build => "Moneta::Adapters::Couch.new(:db => 'adapter_couch')",
|
|
@@ -949,7 +940,7 @@ end
|
|
|
949
940
|
},
|
|
950
941
|
'adapter_daybreak' => {
|
|
951
942
|
:build => 'Moneta::Adapters::Daybreak.new(:file => File.join(make_tempdir, "adapter_daybreak"))',
|
|
952
|
-
:specs => ADAPTER_SPECS
|
|
943
|
+
:specs => ADAPTER_SPECS.returnsame
|
|
953
944
|
},
|
|
954
945
|
'adapter_file' => {
|
|
955
946
|
:build => 'Moneta::Adapters::File.new(:dir => File.join(make_tempdir, "adapter_file"))',
|
|
@@ -962,7 +953,8 @@ end
|
|
|
962
953
|
:dir => 'moneta')",
|
|
963
954
|
# Put Fog into testing mode
|
|
964
955
|
:preamble => "require 'fog'\nFog.mock!\n",
|
|
965
|
-
|
|
956
|
+
# Fog returns same object in mocking mode (in-memory store)
|
|
957
|
+
:specs => ADAPTER_SPECS.without_increment.returnsame
|
|
966
958
|
},
|
|
967
959
|
'adapter_gdbm' => {
|
|
968
960
|
:build => 'Moneta::Adapters::GDBM.new(:file => File.join(make_tempdir, "adapter_gdbm"))',
|
|
@@ -998,11 +990,11 @@ end
|
|
|
998
990
|
},
|
|
999
991
|
'adapter_memory' => {
|
|
1000
992
|
:build => 'Moneta::Adapters::Memory.new',
|
|
1001
|
-
:specs => STANDARD_SPECS.without_transform.
|
|
993
|
+
:specs => STANDARD_SPECS.without_transform.returnsame.without_persist
|
|
1002
994
|
},
|
|
1003
995
|
'adapter_lruhash' => {
|
|
1004
996
|
:build => 'Moneta::Adapters::LRUHash.new',
|
|
1005
|
-
:specs => ADAPTER_SPECS.without_persist,
|
|
997
|
+
:specs => ADAPTER_SPECS.without_persist.returnsame,
|
|
1006
998
|
:tests => %{
|
|
1007
999
|
it 'deletes oldest' do
|
|
1008
1000
|
store = Moneta::Adapters::LRUHash.new(:max_size => 10)
|
|
@@ -1023,7 +1015,7 @@ end}
|
|
|
1023
1015
|
:specs => ADAPTER_SPECS.with_native_expires,
|
|
1024
1016
|
:tests => %{
|
|
1025
1017
|
it 'automatically deletes expired document' do
|
|
1026
|
-
store.store('key', 'val', :expires =>
|
|
1018
|
+
store.store('key', 'val', :expires => 5)
|
|
1027
1019
|
store.instance_variable_get(:@collection).find_one('_id' => ::BSON::Binary.new('key')).should_not be_nil
|
|
1028
1020
|
sleep 70 # Mongo needs up to 60 seconds
|
|
1029
1021
|
store.instance_variable_get(:@collection).find_one('_id' => ::BSON::Binary.new('key')).should be_nil
|
|
@@ -1082,7 +1074,7 @@ end}
|
|
|
1082
1074
|
},
|
|
1083
1075
|
'optionmerger' => {
|
|
1084
1076
|
:store => :Memory,
|
|
1085
|
-
:specs => Specs.new
|
|
1077
|
+
:specs => Specs.new,
|
|
1086
1078
|
:tests => %{
|
|
1087
1079
|
it '#with should return OptionMerger' do
|
|
1088
1080
|
options = {:optionname => :optionvalue}
|
|
@@ -1160,6 +1152,19 @@ it 'has method #prefix' do
|
|
|
1160
1152
|
|
|
1161
1153
|
store.prefix('a').raw.default_options.should == {:store=>{:raw=>true,:prefix=>'a'},:load=>{:raw=>true,:prefix=>'a'},
|
|
1162
1154
|
:delete=>{:raw=>true,:prefix=>'a'},:key? => {:prefix=>'a'},:increment=>{:prefix=>'a'}}
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1157
|
+
it 'supports adding proxis using #with' do
|
|
1158
|
+
compressed_store = store.with(:prefix => 'compressed') do
|
|
1159
|
+
use :Transformer, :value => :zlib
|
|
1160
|
+
end
|
|
1161
|
+
store['key'] = 'uncompressed value'
|
|
1162
|
+
compressed_store['key'] = 'compressed value'
|
|
1163
|
+
store['key'].should == 'uncompressed value'
|
|
1164
|
+
compressed_store['key'].should == 'compressed value'
|
|
1165
|
+
store.key?('compressedkey').should be_true
|
|
1166
|
+
# Check if value is compressed
|
|
1167
|
+
compressed_store['key'].should_not == store['compressedkey']
|
|
1163
1168
|
end}
|
|
1164
1169
|
},
|
|
1165
1170
|
}
|
|
@@ -1299,13 +1304,17 @@ end}
|
|
|
1299
1304
|
|
|
1300
1305
|
(SPECS["store_#{key_type}key_#{val_type}value"] ||= []) << code
|
|
1301
1306
|
|
|
1302
|
-
|
|
1307
|
+
if val_type != 'boolean' && val_type != 'nil' && val_type != 'integer'
|
|
1308
|
+
(SPECS["returndifferent_#{key_type}key_#{val_type}value"] ||= []) << %{it 'guarantees that a different value is retrieved' do
|
|
1303
1309
|
value = #{val1}
|
|
1304
|
-
store[#{key1}] =
|
|
1305
|
-
store[#{key1}].should_not be_equal(
|
|
1310
|
+
store[#{key1}] = value
|
|
1311
|
+
store[#{key1}].should_not be_equal(value)
|
|
1312
|
+
end}
|
|
1313
|
+
(SPECS["returnsame_#{key_type}key_#{val_type}value"] ||= []) << %{it 'guarantees that the same value is retrieved' do
|
|
1314
|
+
value = #{val1}
|
|
1315
|
+
store[#{key1}] = value
|
|
1316
|
+
store[#{key1}].should be_equal(value)
|
|
1306
1317
|
end}
|
|
1307
|
-
if val_type != 'boolean' && val_type != 'nil' && val_type != 'integer'
|
|
1308
|
-
(SPECS["returndifferent_#{key_type}key_#{val_type}value"] ||= []) << code
|
|
1309
1318
|
end
|
|
1310
1319
|
|
|
1311
1320
|
code = %{it 'persists values' do
|
|
@@ -1374,9 +1383,9 @@ it 'supports updating the expiration time in load' do
|
|
|
1374
1383
|
sleep 1
|
|
1375
1384
|
store.load('key2', :expires => 3).should == 'val2'
|
|
1376
1385
|
store['key2'].should == 'val2'
|
|
1377
|
-
sleep
|
|
1386
|
+
sleep 2
|
|
1378
1387
|
store['key2'].should == 'val2'
|
|
1379
|
-
sleep
|
|
1388
|
+
sleep 2
|
|
1380
1389
|
store['key2'].should be_nil
|
|
1381
1390
|
end
|
|
1382
1391
|
|
|
@@ -1400,9 +1409,9 @@ it 'supports updating the expiration time in key?' do
|
|
|
1400
1409
|
sleep 1
|
|
1401
1410
|
store.key?('key2', :expires => 3).should be_true
|
|
1402
1411
|
store['key2'].should == 'val2'
|
|
1403
|
-
sleep
|
|
1412
|
+
sleep 2
|
|
1404
1413
|
store['key2'].should == 'val2'
|
|
1405
|
-
sleep
|
|
1414
|
+
sleep 2
|
|
1406
1415
|
store['key2'].should be_nil
|
|
1407
1416
|
end
|
|
1408
1417
|
|
|
@@ -1426,9 +1435,9 @@ it 'supports updating the expiration time in fetch' do
|
|
|
1426
1435
|
sleep 1
|
|
1427
1436
|
store.fetch('key1', nil, :expires => 3).should == 'val1'
|
|
1428
1437
|
store['key1'].should == 'val1'
|
|
1429
|
-
sleep
|
|
1438
|
+
sleep 2
|
|
1430
1439
|
store['key1'].should == 'val1'
|
|
1431
|
-
sleep
|
|
1440
|
+
sleep 2
|
|
1432
1441
|
store['key1'].should be_nil
|
|
1433
1442
|
end
|
|
1434
1443
|
|