readthis 1.0.0.pre.beta → 1.0.0.pre.rc.1
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 +4 -4
- data/README.md +9 -9
- data/lib/active_support/cache/readthis_store.rb +1 -1
- data/lib/readthis/cache.rb +11 -16
- data/lib/readthis/entity.rb +1 -2
- data/lib/readthis/expanders.rb +1 -1
- data/lib/readthis/serializers.rb +28 -17
- data/lib/readthis/version.rb +1 -1
- data/spec/readthis/cache_spec.rb +14 -22
- data/spec/readthis/entity_spec.rb +0 -10
- data/spec/readthis/expanders_spec.rb +1 -1
- data/spec/readthis/serializers_spec.rb +21 -6
- data/spec/spec_helper.rb +1 -3
- metadata +3 -23
- data/.gitignore +0 -15
- data/.rspec +0 -2
- data/.travis.yml +0 -15
- data/CHANGELOG.md +0 -135
- data/CONTRIBUTING.md +0 -14
- data/Gemfile +0 -14
- data/LICENSE.txt +0 -22
- data/PERFORMANCE.md +0 -73
- data/Rakefile +0 -2
- data/benchmarks/composing.rb +0 -43
- data/benchmarks/compressed.rb +0 -74
- data/benchmarks/driver.rb +0 -18
- data/benchmarks/generic.rb +0 -30
- data/benchmarks/marshalling.rb +0 -38
- data/benchmarks/memory.rb +0 -11
- data/benchmarks/multi.rb +0 -60
- data/benchmarks/parsing.rb +0 -42
- data/benchmarks/profile.rb +0 -20
- data/bin/rspec +0 -16
- data/readthis.gemspec +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c641f0b14297f5f65cc9e2a36dc525c92e2f4a48
|
4
|
+
data.tar.gz: cf5625a9a3b874f5f715979c615ee0db5c27daad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3774c714c24caa36cdb07b8ce5b39f1694ed2e9b9b116b2b3c463fc516e2b2bfebf68e1481c5181502fddd76e3690ae3af7bfcf7ef3210c5ae8ca634ad3f16c9
|
7
|
+
data.tar.gz: 274020a823960b9f4b7efdf101d02b3cc6a08074c508a6b32d4c990de0ccacf47571d98a1e74796f2d12d417971c297dffdc81abc1e24b3a770a74c64874810a
|
data/README.md
CHANGED
@@ -96,28 +96,28 @@ config.cache_store = :readthis_store, {
|
|
96
96
|
}
|
97
97
|
```
|
98
98
|
|
99
|
-
###
|
99
|
+
### Serializing
|
100
100
|
|
101
|
-
Readthis uses Ruby's `Marshal` module for
|
102
|
-
|
103
|
-
|
101
|
+
Readthis uses Ruby's `Marshal` module for serializing all values by default.
|
102
|
+
This isn't always the fastest option, and depending on your use case it may be
|
103
|
+
desirable to use a faster but less flexible serializer.
|
104
104
|
|
105
|
-
By default Readthis knows about 3 different serializers
|
105
|
+
By default Readthis knows about 3 different serializers:
|
106
106
|
|
107
107
|
* Marshal
|
108
108
|
* JSON
|
109
109
|
* Passthrough
|
110
110
|
|
111
111
|
If all cached data can safely be represented as a string then use the
|
112
|
-
pass-through
|
112
|
+
pass-through serializer:
|
113
113
|
|
114
114
|
```ruby
|
115
115
|
Readthis::Cache.new(marshal: Readthis::Passthrough)
|
116
116
|
```
|
117
117
|
|
118
|
-
You can introduce up to four additional
|
119
|
-
the Readthis module. For example, if you wanted to use
|
120
|
-
|
118
|
+
You can introduce up to four additional serializers by configuring `serializers`
|
119
|
+
on the Readthis module. For example, if you wanted to use the extremely fast Oj
|
120
|
+
library for JSON serialization:
|
121
121
|
|
122
122
|
```ruby
|
123
123
|
Readthis.serializers << Oj
|
data/lib/readthis/cache.rb
CHANGED
@@ -7,7 +7,7 @@ require 'connection_pool'
|
|
7
7
|
|
8
8
|
module Readthis
|
9
9
|
class Cache
|
10
|
-
attr_reader :entity, :
|
10
|
+
attr_reader :entity, :options, :pool
|
11
11
|
|
12
12
|
# Provide a class level lookup of the proper notifications module.
|
13
13
|
# Instrumention is expected to occur within applications that have
|
@@ -39,9 +39,7 @@ module Readthis
|
|
39
39
|
# Readthis::Cache.new(compress: true, compression_threshold: 2048)
|
40
40
|
#
|
41
41
|
def initialize(options = {})
|
42
|
-
@options
|
43
|
-
@expires_in = options.fetch(:expires_in, nil)
|
44
|
-
@namespace = options.fetch(:namespace, nil)
|
42
|
+
@options = options
|
45
43
|
|
46
44
|
@entity = Readthis::Entity.new(
|
47
45
|
marshal: options.fetch(:marshal, Marshal),
|
@@ -171,7 +169,7 @@ module Readthis
|
|
171
169
|
# cache.increment('counter', 2) # => 3
|
172
170
|
#
|
173
171
|
def increment(key, amount = 1, options = {})
|
174
|
-
invoke(:increment, key) do |
|
172
|
+
invoke(:increment, key) do |_store|
|
175
173
|
alter(key, amount, options)
|
176
174
|
end
|
177
175
|
end
|
@@ -192,7 +190,7 @@ module Readthis
|
|
192
190
|
# cache.decrement('counter', 2) # => 17
|
193
191
|
#
|
194
192
|
def decrement(key, amount = 1, options = {})
|
195
|
-
invoke(:decrement, key) do |
|
193
|
+
invoke(:decrement, key) do |_store|
|
196
194
|
alter(key, amount * -1, options)
|
197
195
|
end
|
198
196
|
end
|
@@ -271,13 +269,13 @@ module Readthis
|
|
271
269
|
extracted = extract_options!(keys)
|
272
270
|
missing = {}
|
273
271
|
|
274
|
-
invoke(:fetch_multi, keys) do |
|
272
|
+
invoke(:fetch_multi, keys) do |_store|
|
275
273
|
results.each do |key, value|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
274
|
+
next unless value.nil?
|
275
|
+
|
276
|
+
value = yield(key)
|
277
|
+
missing[key] = value
|
278
|
+
results[key] = value
|
281
279
|
end
|
282
280
|
end
|
283
281
|
|
@@ -354,10 +352,7 @@ module Readthis
|
|
354
352
|
end
|
355
353
|
|
356
354
|
def merged_options(options)
|
357
|
-
options
|
358
|
-
options[:namespace] ||= namespace
|
359
|
-
options[:expires_in] ||= expires_in
|
360
|
-
options
|
355
|
+
(options || {}).merge!(@options)
|
361
356
|
end
|
362
357
|
|
363
358
|
def pool_options(options)
|
data/lib/readthis/entity.rb
CHANGED
@@ -9,7 +9,6 @@ module Readthis
|
|
9
9
|
}.freeze
|
10
10
|
|
11
11
|
COMPRESSED_FLAG = 0x8
|
12
|
-
MARSHAL_FLAG = 0x3
|
13
12
|
|
14
13
|
# Creates a Readthis::Entity with default options. Each option can be
|
15
14
|
# overridden later when entities are being dumped.
|
@@ -105,7 +104,7 @@ module Readthis
|
|
105
104
|
flags = string[0].unpack('C').first
|
106
105
|
|
107
106
|
if flags < 16
|
108
|
-
marshal = serializers.rassoc(flags
|
107
|
+
marshal = serializers.rassoc(flags)
|
109
108
|
compress = (flags & COMPRESSED_FLAG) != 0
|
110
109
|
|
111
110
|
[marshal, compress, string[1..-1]]
|
data/lib/readthis/expanders.rb
CHANGED
@@ -7,7 +7,7 @@ module Readthis
|
|
7
7
|
when key.is_a?(Array)
|
8
8
|
key.flat_map { |elem| expand_key(elem) }.join('/')
|
9
9
|
when key.is_a?(Hash)
|
10
|
-
key.sort_by { |
|
10
|
+
key.sort_by { |hkey, _| hkey.to_s }.map { |hkey, val| "#{hkey}=#{val}" }.join('/')
|
11
11
|
when key.respond_to?(:to_param)
|
12
12
|
key.to_param
|
13
13
|
else
|
data/lib/readthis/serializers.rb
CHANGED
@@ -2,8 +2,9 @@ require 'json'
|
|
2
2
|
require 'readthis/passthrough'
|
3
3
|
|
4
4
|
module Readthis
|
5
|
-
SerializersFrozenError = Class.new(
|
6
|
-
SerializersLimitError = Class.new(
|
5
|
+
SerializersFrozenError = Class.new(StandardError)
|
6
|
+
SerializersLimitError = Class.new(StandardError)
|
7
|
+
UnknownSerializerError = Class.new(StandardError)
|
7
8
|
|
8
9
|
class Serializers
|
9
10
|
BASE_SERIALIZERS = {
|
@@ -38,9 +39,9 @@ module Readthis
|
|
38
39
|
def <<(serializer)
|
39
40
|
case
|
40
41
|
when serializers.frozen?
|
41
|
-
|
42
|
+
fail SerializersFrozenError
|
42
43
|
when serializers.length > SERIALIZER_LIMIT
|
43
|
-
|
44
|
+
fail SerializersLimitError
|
44
45
|
else
|
45
46
|
@serializers[serializer] = flags.max.succ
|
46
47
|
@inverted = @serializers.invert
|
@@ -63,36 +64,46 @@ module Readthis
|
|
63
64
|
@inverted = @serializers.invert
|
64
65
|
end
|
65
66
|
|
66
|
-
# Find a flag
|
67
|
+
# Find a flag for a serializer object.
|
67
68
|
#
|
68
69
|
# @param [Object] Look up a flag by object
|
69
|
-
# @return [Number] Corresponding flag for the
|
70
|
+
# @return [Number] Corresponding flag for the serializer object
|
71
|
+
# @raise [UnknownSerializerError] Indicates that a serializer was
|
72
|
+
# specified, but hasn't been configured for usage.
|
70
73
|
#
|
71
74
|
# @example
|
72
75
|
#
|
73
|
-
# serializers.assoc(
|
76
|
+
# serializers.assoc(JSON) #=> 1
|
74
77
|
#
|
75
|
-
def assoc(
|
76
|
-
serializers[
|
78
|
+
def assoc(serializer)
|
79
|
+
flag = serializers[serializer]
|
80
|
+
|
81
|
+
unless flag
|
82
|
+
fail UnknownSerializerError, "'#{serializer}' hasn't been configured"
|
83
|
+
end
|
84
|
+
|
85
|
+
flag
|
77
86
|
end
|
78
87
|
|
79
|
-
# Find a
|
88
|
+
# Find a serializer object by flag value.
|
89
|
+
#
|
90
|
+
# @param [Number] Flag to look up the serializer object by
|
91
|
+
# @return [Module] The serializer object
|
80
92
|
#
|
81
|
-
# @
|
82
|
-
#
|
93
|
+
# @example
|
94
|
+
#
|
95
|
+
# serializers.rassoc(1) #=> Marshal
|
83
96
|
#
|
84
97
|
def rassoc(flag)
|
85
|
-
inverted[flag]
|
98
|
+
inverted[flag & inverted.length]
|
86
99
|
end
|
87
100
|
|
88
|
-
#
|
89
|
-
#
|
101
|
+
# @private
|
90
102
|
def marshals
|
91
103
|
serializers.keys
|
92
104
|
end
|
93
105
|
|
94
|
-
#
|
95
|
-
#
|
106
|
+
# @private
|
96
107
|
def flags
|
97
108
|
serializers.values
|
98
109
|
end
|
data/lib/readthis/version.rb
CHANGED
data/spec/readthis/cache_spec.rb
CHANGED
@@ -8,18 +8,6 @@ RSpec.describe Readthis::Cache do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '#initialize' do
|
11
|
-
it 'accepts and persists a namespace' do
|
12
|
-
cache = Readthis::Cache.new(namespace: 'kash')
|
13
|
-
|
14
|
-
expect(cache.namespace).to eq('kash')
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'accepts and persists an expiration' do
|
18
|
-
cache = Readthis::Cache.new(expires_in: 10)
|
19
|
-
|
20
|
-
expect(cache.expires_in).to eq(10)
|
21
|
-
end
|
22
|
-
|
23
11
|
it 'makes options available' do
|
24
12
|
cache = Readthis::Cache.new(namespace: 'cache', expires_in: 1)
|
25
13
|
|
@@ -89,20 +77,20 @@ RSpec.describe Readthis::Cache do
|
|
89
77
|
|
90
78
|
it 'uses globally configured serializers' do
|
91
79
|
custom = Class.new do
|
92
|
-
def self.dump(
|
93
|
-
|
80
|
+
def self.dump(value)
|
81
|
+
value
|
94
82
|
end
|
95
83
|
|
96
|
-
def self.load(
|
97
|
-
|
84
|
+
def self.load(value)
|
85
|
+
value
|
98
86
|
end
|
99
87
|
end
|
100
88
|
|
101
89
|
Readthis.serializers << custom
|
102
90
|
|
103
|
-
cache.write('customized', '
|
91
|
+
cache.write('customized', 'some value', marshal: custom)
|
104
92
|
|
105
|
-
expect(cache.read('customized')).to
|
93
|
+
expect(cache.read('customized')).to eq('some value')
|
106
94
|
end
|
107
95
|
end
|
108
96
|
|
@@ -179,7 +167,7 @@ RSpec.describe Readthis::Cache do
|
|
179
167
|
expect(cache.read_multi('a', 'b', 'c')).to eq(
|
180
168
|
'a' => 1,
|
181
169
|
'b' => 2,
|
182
|
-
'c' => '3'
|
170
|
+
'c' => '3'
|
183
171
|
)
|
184
172
|
end
|
185
173
|
|
@@ -189,7 +177,7 @@ RSpec.describe Readthis::Cache do
|
|
189
177
|
|
190
178
|
expect(cache.read_multi('d', 'e', namespace: 'cache')).to eq(
|
191
179
|
'd' => 1,
|
192
|
-
'e' => 2
|
180
|
+
'e' => 2
|
193
181
|
)
|
194
182
|
end
|
195
183
|
|
@@ -208,7 +196,11 @@ RSpec.describe Readthis::Cache do
|
|
208
196
|
end
|
209
197
|
|
210
198
|
it 'respects passed options' do
|
211
|
-
cache.write_multi(
|
199
|
+
cache.write_multi(
|
200
|
+
{ 'a' => 1, 'b' => 2 },
|
201
|
+
namespace: 'multi',
|
202
|
+
expires_in: 1
|
203
|
+
)
|
212
204
|
|
213
205
|
expect(cache.read('a')).to be_nil
|
214
206
|
expect(cache.read('a', namespace: 'multi')).to eq(1)
|
@@ -227,7 +219,7 @@ RSpec.describe Readthis::Cache do
|
|
227
219
|
expect(results).to eq(
|
228
220
|
'a' => 1,
|
229
221
|
'b' => 'bb',
|
230
|
-
'c' => 3
|
222
|
+
'c' => 3
|
231
223
|
)
|
232
224
|
|
233
225
|
expect(cache.read('b')).to eq('bb')
|
@@ -131,16 +131,6 @@ RSpec.describe Readthis::Entity do
|
|
131
131
|
expect(value).to eq(string)
|
132
132
|
end
|
133
133
|
|
134
|
-
it 'can reconstruct longer qualified module names' do
|
135
|
-
string = 'a' * 30
|
136
|
-
entity = Readthis::Entity.new
|
137
|
-
marked = entity.compose(string, Readthis::Passthrough, false)
|
138
|
-
|
139
|
-
marshal, _, _ = entity.decompose(marked)
|
140
|
-
|
141
|
-
expect(marshal).to eq(Readthis::Passthrough)
|
142
|
-
end
|
143
|
-
|
144
134
|
it 'returns the original string without a marker' do
|
145
135
|
string = 'the quick brown fox'
|
146
136
|
entity = Readthis::Entity.new
|
@@ -19,7 +19,7 @@ RSpec.describe Readthis::Expanders do
|
|
19
19
|
it 'expands an array of objects' do
|
20
20
|
object = double(cache_key: 'gamma')
|
21
21
|
|
22
|
-
expect(expand([
|
22
|
+
expect(expand(%w[alpha beta])).to eq('alpha/beta')
|
23
23
|
expect(expand([object, object])).to eq('gamma/gamma')
|
24
24
|
end
|
25
25
|
|
@@ -11,7 +11,7 @@ RSpec.describe Readthis::Serializers do
|
|
11
11
|
serializers << CustomSerializer
|
12
12
|
|
13
13
|
expect(serializers.marshals).to include(CustomSerializer)
|
14
|
-
expect(serializers.flags).to eq(
|
14
|
+
expect(serializers.flags).to eq([1, 2, 3, 4])
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'increments flags' do
|
@@ -25,9 +25,9 @@ RSpec.describe Readthis::Serializers do
|
|
25
25
|
it 'prevents more than seven serializers' do
|
26
26
|
serializers = Readthis::Serializers.new
|
27
27
|
|
28
|
-
expect
|
28
|
+
expect do
|
29
29
|
10.times { serializers << Class.new }
|
30
|
-
|
30
|
+
end.to raise_error(Readthis::SerializersLimitError)
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
@@ -37,6 +37,14 @@ RSpec.describe Readthis::Serializers do
|
|
37
37
|
|
38
38
|
expect(serializers.assoc(Marshal)).to eq(0x1)
|
39
39
|
end
|
40
|
+
|
41
|
+
it 'raises a helpful error when the serializer is unknown' do
|
42
|
+
serializers = Readthis::Serializers.new
|
43
|
+
|
44
|
+
expect do
|
45
|
+
serializers.assoc(CustomSerializer)
|
46
|
+
end.to raise_error(Readthis::UnknownSerializerError)
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
describe '#rassoc' do
|
@@ -45,6 +53,13 @@ RSpec.describe Readthis::Serializers do
|
|
45
53
|
|
46
54
|
expect(serializers.rassoc(1)).to eq(Marshal)
|
47
55
|
end
|
56
|
+
|
57
|
+
it 'returns custom serializers' do
|
58
|
+
serializers = Readthis::Serializers.new
|
59
|
+
serializers << CustomSerializer
|
60
|
+
|
61
|
+
expect(serializers.rassoc(4)).to eq(CustomSerializer)
|
62
|
+
end
|
48
63
|
end
|
49
64
|
|
50
65
|
describe '#freeze!' do
|
@@ -53,9 +68,9 @@ RSpec.describe Readthis::Serializers do
|
|
53
68
|
|
54
69
|
serializers.freeze!
|
55
70
|
|
56
|
-
expect
|
71
|
+
expect do
|
57
72
|
serializers << CustomSerializer
|
58
|
-
|
73
|
+
end.to raise_error(Readthis::SerializersFrozenError)
|
59
74
|
end
|
60
75
|
end
|
61
76
|
|
@@ -66,7 +81,7 @@ RSpec.describe Readthis::Serializers do
|
|
66
81
|
serializers << Class.new
|
67
82
|
serializers.reset!
|
68
83
|
|
69
|
-
expect(serializers.
|
84
|
+
expect(serializers.serializers.length).to eq(3)
|
70
85
|
end
|
71
86
|
end
|
72
87
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,9 +16,7 @@ RSpec.configure do |config|
|
|
16
16
|
|
17
17
|
config.disable_monkey_patching!
|
18
18
|
|
19
|
-
if config.files_to_run.one?
|
20
|
-
config.default_formatter = 'doc'
|
21
|
-
end
|
19
|
+
config.default_formatter = 'doc' if config.files_to_run.one?
|
22
20
|
|
23
21
|
config.order = :random
|
24
22
|
Kernel.srand config.seed
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: readthis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.rc.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Parker Selbert
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -94,33 +94,14 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.1'
|
97
|
-
description:
|
97
|
+
description:
|
98
98
|
email:
|
99
99
|
- parker@sorentwo.com
|
100
100
|
executables: []
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
-
- ".gitignore"
|
105
|
-
- ".rspec"
|
106
|
-
- ".travis.yml"
|
107
|
-
- CHANGELOG.md
|
108
|
-
- CONTRIBUTING.md
|
109
|
-
- Gemfile
|
110
|
-
- LICENSE.txt
|
111
|
-
- PERFORMANCE.md
|
112
104
|
- README.md
|
113
|
-
- Rakefile
|
114
|
-
- benchmarks/composing.rb
|
115
|
-
- benchmarks/compressed.rb
|
116
|
-
- benchmarks/driver.rb
|
117
|
-
- benchmarks/generic.rb
|
118
|
-
- benchmarks/marshalling.rb
|
119
|
-
- benchmarks/memory.rb
|
120
|
-
- benchmarks/multi.rb
|
121
|
-
- benchmarks/parsing.rb
|
122
|
-
- benchmarks/profile.rb
|
123
|
-
- bin/rspec
|
124
105
|
- lib/active_support/cache/readthis_store.rb
|
125
106
|
- lib/readthis.rb
|
126
107
|
- lib/readthis/cache.rb
|
@@ -130,7 +111,6 @@ files:
|
|
130
111
|
- lib/readthis/passthrough.rb
|
131
112
|
- lib/readthis/serializers.rb
|
132
113
|
- lib/readthis/version.rb
|
133
|
-
- readthis.gemspec
|
134
114
|
- spec/readthis/cache_spec.rb
|
135
115
|
- spec/readthis/entity_spec.rb
|
136
116
|
- spec/readthis/expanders_spec.rb
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/CHANGELOG.md
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
## v1.0.0-beta
|
2
|
-
|
3
|
-
- Breaking: This change is necessary for the consistency and portability of
|
4
|
-
values going forward. All entities are now written with a set of option flags
|
5
|
-
as the initial byte. This flag is later used to determine whether the entity
|
6
|
-
was compressed and what was used to marshal it. There are a number of
|
7
|
-
advantages to this approach, consistency and reliability being the most
|
8
|
-
important. See [readthis#17][pull-17] for additional background.
|
9
|
-
- Added: Per-entity options can be passed through to any cache method that
|
10
|
-
writes a value (`write`, `fetch`, etc). For example, this allows certain
|
11
|
-
entities to be cached as JSON while all other entities are cached using
|
12
|
-
Marshal. Thanks to @fabn.
|
13
|
-
- Fixed: A hash containing the cache key is passed as the payload for
|
14
|
-
`ActiveSupport::Notifications` instrumentation, rather than the key directly.
|
15
|
-
This moves the implementation in-line with the tests for the code, and
|
16
|
-
prevents errors from being masked when an error occurs inside an instrumented
|
17
|
-
block. [readthis#20][pull-20]. Discovered by @banister and fixed by @workmad3.
|
18
|
-
|
19
|
-
[pull-17]: https://github.com/sorentwo/readthis/pull/17
|
20
|
-
[pull-20]: https://github.com/sorentwo/readthis/pull/20
|
21
|
-
|
22
|
-
## v0.8.1 2015-09-04
|
23
|
-
|
24
|
-
- Changed: `Readthis::Cache` now has an accessor for the options that were
|
25
|
-
passed during initialization. This is primarily to support the session store
|
26
|
-
middleware provided by `ActionDispatch`. See [readthis#16][issue-16].
|
27
|
-
- Fixed: Caching `nil` values is now possible. Previously the value would be
|
28
|
-
converted into a blank string, causing a Marshal error when loading the data.
|
29
|
-
There is still some non-standard handling of `nil` within `fetch` or
|
30
|
-
`fetch_multi`, where a cached `nil` value will always result in a cache miss.
|
31
|
-
See [readthis#15][issue-15].
|
32
|
-
- Fixed: Entity compression was broken, it wouldn't unload data when the
|
33
|
-
compressed size was below the compression limit. Data is now decompressed
|
34
|
-
when it can the value looks to be compressed, falling back to the initial
|
35
|
-
value when decompression fails. See [readthis#13][issue-13] for details.
|
36
|
-
|
37
|
-
[issue-13]: https://github.com/sorentwo/readthis/issues/13
|
38
|
-
[issue-15]: https://github.com/sorentwo/readthis/issues/15
|
39
|
-
[issue-16]: https://github.com/sorentwo/readthis/issues/16
|
40
|
-
|
41
|
-
## v0.8.0 2015-08-26
|
42
|
-
|
43
|
-
- Breaking: The initializer now takes a single options argument instead of a
|
44
|
-
`url` and `options` separately. This allows the underlying redis client to
|
45
|
-
accept any options, rather than just the driver. For example, it's now
|
46
|
-
possible to use Readthis with sentinel directly through the configuration.
|
47
|
-
- Changed: The `hiredis` driver is *no longer the default*. In order to use the
|
48
|
-
vastly faster `hiredis` driver you need to pass it in during construction.
|
49
|
-
See [readthis#9][issue-9] for more discussion.
|
50
|
-
|
51
|
-
[issue-9]: https://github.com/sorentwo/readthis/issues/9
|
52
|
-
|
53
|
-
## v0.7.0 2015-08-11
|
54
|
-
|
55
|
-
- Changed: Entity initialization uses an options hash rather than keyword
|
56
|
-
arguments. This allows flexibility with older Ruby versions (1.9) that aren't
|
57
|
-
officially supported.
|
58
|
-
- Changed: There is no longer a hard dependency on `hiredis`, though it is the
|
59
|
-
default. The redis driver can be configured by passing a `driver: :ruby`
|
60
|
-
option through to the constructor.
|
61
|
-
|
62
|
-
## v0.6.2 2015-04-28
|
63
|
-
|
64
|
-
- Fixed: Set expiration during `write_multi`, primarily effecting `fetch_multi`.
|
65
|
-
This fixes the real issue underlying the change in `v0.6.1`.
|
66
|
-
|
67
|
-
## v0.6.1 2015-04-28
|
68
|
-
|
69
|
-
- Changed: Expiration values are always cast to an integer before use in write
|
70
|
-
operations. This prevents subtle ActiveSupport bugs where the value would be
|
71
|
-
ignored by `setex`.
|
72
|
-
|
73
|
-
## v0.6.0 2015-03-09
|
74
|
-
|
75
|
-
- Fixed: Safely handle calling `read_multi` without any keys. [Michael Rykov]
|
76
|
-
- Fixed: Pointed `redis-activesupport` at master. Only effected development and
|
77
|
-
testing.
|
78
|
-
- Added: A `write_multi` method is no available to bulk set keys and values. It
|
79
|
-
is used by `fetch_multi` internally to ensure that there are at most two Redis
|
80
|
-
calls.
|
81
|
-
|
82
|
-
## v0.5.2 2015-01-09
|
83
|
-
|
84
|
-
- Fixed: Remove the `pipeline` around `fetch_multi` writing. This will slow down
|
85
|
-
`fetch_multi` in cache miss situations for now. It prevents a difficult to
|
86
|
-
track down exception in multi-threaded situations.
|
87
|
-
|
88
|
-
## v0.5.1 2014-12-30
|
89
|
-
|
90
|
-
- Fixed: The `clear` method now accepts an argument for compatibility with other
|
91
|
-
caches. The argument is not actually used for anything.
|
92
|
-
- Changed: The `delete` method will always return a boolean value rather than an
|
93
|
-
integer.
|
94
|
-
- Changed: Avoid multiple instrumentation calls and pool checkouts within
|
95
|
-
`fetch_multi` calls.
|
96
|
-
|
97
|
-
## v0.5.0 2014-12-12
|
98
|
-
|
99
|
-
- Added: All read and write operations are marshalled to and from storage. This
|
100
|
-
allows hashes, arrays, etc. to be restored instead of always returning a
|
101
|
-
string. Unlike `ActiveSupport::Store::Entity`, no new objects are allocated
|
102
|
-
for each entity, reducing GC and improving performance.
|
103
|
-
- Fixed: Increment/Decrement interface was only accepting two params instead of
|
104
|
-
three. Now accepts `amount` as the second parameter.
|
105
|
-
- Changed: Increment/Decrement no longer use `incby` and `decby`, as they don't
|
106
|
-
work with marshalled values. This means they are not entirely atomic, so race
|
107
|
-
conditions are possible.
|
108
|
-
|
109
|
-
## v0.4.0 2014-12-11
|
110
|
-
|
111
|
-
- Added: Force the use of `hiredis` as the adapter. It is dramatically faster,
|
112
|
-
but prevents the project from being used in `jruby`. If we get interest from
|
113
|
-
some `jruby` projects we can soften the requirement.
|
114
|
-
- Added: Compression! Adheres to the `ActiveSupport::Store` documentation.
|
115
|
-
- Fixed: Gracefully handle `nil` passed as `options` to any cache method.
|
116
|
-
|
117
|
-
## v0.3.0 2014-12-01
|
118
|
-
|
119
|
-
- Added: Use `to_param` for key expansion, only when available. Makes it
|
120
|
-
possible to extract a key from any object when ActiveSupport is loaded.
|
121
|
-
- Added: Expand hashes as cache keys.
|
122
|
-
- Changed: Use `mget` for `read_multi`, faster and more synchronous than relying on
|
123
|
-
`pipelined`.
|
124
|
-
- Changed: Delimit compound objects with a slash rather than a colon.
|
125
|
-
|
126
|
-
## v0.2.0 2014-11-24
|
127
|
-
|
128
|
-
- Added: Instrument all caching methods. Will use `ActiveSupport::Notifications`
|
129
|
-
if available, otherwise falls back to a polyfill.
|
130
|
-
- Added: Expand objects with a `cache_key` method and arrays of strings or objects into
|
131
|
-
consistent naespaced keys.
|
132
|
-
|
133
|
-
## v0.1.0 2014-11-22
|
134
|
-
|
135
|
-
- Initial release! Working as a drop in replacement for `redis_store`.
|
data/CONTRIBUTING.md
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# Contributing
|
2
|
-
|
3
|
-
## Open an Issue
|
4
|
-
|
5
|
-
Let us know about bugs. Include your version of Readthis, Ruby, and the
|
6
|
-
environment you are using.
|
7
|
-
|
8
|
-
## Submit a Pull Request
|
9
|
-
|
10
|
-
1. Fork it ( https://github.com/sorentwo/readthis/fork )
|
11
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
12
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
13
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
14
|
-
5. Create a new Pull Request
|
data/Gemfile
DELETED
data/LICENSE.txt
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2014 Parker Selbert
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/PERFORMANCE.md
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
Results from the various benchmarks in `./bencharks`. Hardware doesn't matter
|
2
|
-
much, as we're simply looking for a comparison against other libraries and prior
|
3
|
-
verions.
|
4
|
-
|
5
|
-
## Footprint
|
6
|
-
|
7
|
-
Footprint compared to `redis-activesupport`:
|
8
|
-
|
9
|
-
```
|
10
|
-
# Total allocated objects after require
|
11
|
-
readthis: 20602
|
12
|
-
redis-activesupport: 78630
|
13
|
-
```
|
14
|
-
|
15
|
-
## Performance
|
16
|
-
|
17
|
-
Performance compared to `dalli` and `redis-activesupport`:
|
18
|
-
|
19
|
-
```
|
20
|
-
Raw Read Multi:
|
21
|
-
Calculating -------------------------------------
|
22
|
-
readthis:read-multi 358.000 i/100ms
|
23
|
-
redisas:read-multi 94.000 i/100ms
|
24
|
-
dalli:read-multi 99.000 i/100ms
|
25
|
-
-------------------------------------------------
|
26
|
-
readthis:read-multi 3.800k (± 2.3%) i/s - 19.332k
|
27
|
-
redisas:read-multi 962.199 (± 3.6%) i/s - 4.888k
|
28
|
-
dalli:read-multi 995.353 (± 1.1%) i/s - 5.049k
|
29
|
-
|
30
|
-
Comparison:
|
31
|
-
readthis:read-multi: 3799.8 i/s
|
32
|
-
dalli:read-multi: 995.4 i/s - 3.82x slower
|
33
|
-
redisas:read-multi: 962.2 i/s - 3.95x slower
|
34
|
-
|
35
|
-
Raw Fetch Multi:
|
36
|
-
Calculating -------------------------------------
|
37
|
-
readthis:fetch-multi 336.000 i/100ms
|
38
|
-
redisas:fetch-multi 86.000 i/100ms
|
39
|
-
dalli:fetch-multi 102.000 i/100ms
|
40
|
-
-------------------------------------------------
|
41
|
-
readthis:fetch-multi 3.424k (± 2.6%) i/s - 17.136k
|
42
|
-
redisas:fetch-multi 874.803 (± 2.7%) i/s - 4.386k
|
43
|
-
dalli:fetch-multi 1.028k (± 1.2%) i/s - 5.202k
|
44
|
-
|
45
|
-
Comparison:
|
46
|
-
readthis:fetch-multi: 3424.2 i/s
|
47
|
-
dalli:fetch-multi: 1027.7 i/s - 3.33x slower
|
48
|
-
redisas:fetch-multi: 874.8 i/s - 3.91x slower
|
49
|
-
|
50
|
-
Compressed Writes:
|
51
|
-
Calculating -------------------------------------
|
52
|
-
readthis:write 924.000 i/100ms
|
53
|
-
dalli:write 903.000 i/100ms
|
54
|
-
-------------------------------------------------
|
55
|
-
readthis:write 10.105k (± 4.9%) i/s - 50.820k
|
56
|
-
dalli:write 9.662k (± 1.6%) i/s - 48.762k
|
57
|
-
|
58
|
-
Comparison:
|
59
|
-
readthis:write: 10105.3 i/s
|
60
|
-
dalli:write: 9662.4 i/s - 1.05x slower
|
61
|
-
|
62
|
-
Compressed Read Multi:
|
63
|
-
Calculating -------------------------------------
|
64
|
-
readthis:read_multi 325.000 i/100ms
|
65
|
-
dalli:read_multi 100.000 i/100ms
|
66
|
-
-------------------------------------------------
|
67
|
-
readthis:read_multi 3.357k (± 2.3%) i/s - 16.900k
|
68
|
-
dalli:read_multi 1.014k (± 3.1%) i/s - 5.100k
|
69
|
-
|
70
|
-
Comparison:
|
71
|
-
readthis:read_multi: 3356.5 i/s
|
72
|
-
dalli:read_multi: 1014.1 i/s - 3.31x slower
|
73
|
-
```
|
data/Rakefile
DELETED
data/benchmarks/composing.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
|
3
|
-
def compose_a(marshal, compress)
|
4
|
-
prefix = ''
|
5
|
-
prefix << 'R|'.freeze
|
6
|
-
prefix << marshal.name.ljust(24)
|
7
|
-
prefix << (compress ? '1'.freeze : '0'.freeze)
|
8
|
-
prefix << 1
|
9
|
-
prefix << '|R'.freeze
|
10
|
-
end
|
11
|
-
|
12
|
-
def compose_b(marshal, compress)
|
13
|
-
"R|#{marshal.name.ljust(24)}#{compress ? '1'.freeze : '0'.freeze}1|R"
|
14
|
-
end
|
15
|
-
|
16
|
-
def compose_c(marshal, compress)
|
17
|
-
name = marshal.name.ljust(24)
|
18
|
-
comp = compress ? '1'.freeze : '0'.freeze
|
19
|
-
|
20
|
-
"R|#{name}#{comp}1|R"
|
21
|
-
end
|
22
|
-
|
23
|
-
SERIALIZER_FLAG = { Marshal => 0x1 }.freeze
|
24
|
-
COMPRESSED_FLAG = 0x8
|
25
|
-
|
26
|
-
# | 0000 | 0 | 000 |
|
27
|
-
# four unused bits, # 1 compression bit, 3 bits for serializer, allow up to 8
|
28
|
-
# different marshalers
|
29
|
-
def compose_d(marshal, compress)
|
30
|
-
flags = SERIALIZER_FLAG[marshal]
|
31
|
-
flags |= COMPRESSED_FLAG if compress
|
32
|
-
|
33
|
-
[flags].pack('C')
|
34
|
-
end
|
35
|
-
|
36
|
-
Benchmark.ips do |x|
|
37
|
-
x.report('a') { compose_a(Marshal, true) }
|
38
|
-
x.report('b') { compose_b(Marshal, true) }
|
39
|
-
x.report('c') { compose_c(Marshal, true) }
|
40
|
-
x.report('d') { compose_d(Marshal, true) }
|
41
|
-
|
42
|
-
x.compare!
|
43
|
-
end
|
data/benchmarks/compressed.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
Bundler.setup
|
4
|
-
|
5
|
-
require 'benchmark/ips'
|
6
|
-
require 'dalli'
|
7
|
-
require 'active_support'
|
8
|
-
require 'active_support/cache/dalli_store'
|
9
|
-
require 'readthis'
|
10
|
-
|
11
|
-
dalli = ActiveSupport::Cache::DalliStore.new(
|
12
|
-
'localhost',
|
13
|
-
pool_size: 5,
|
14
|
-
compressed: true,
|
15
|
-
compression_threshold: 8
|
16
|
-
)
|
17
|
-
|
18
|
-
readthis = Readthis::Cache.new(
|
19
|
-
pool_size: 5,
|
20
|
-
compressed: true,
|
21
|
-
compression_threshold: 128
|
22
|
-
)
|
23
|
-
|
24
|
-
KEY = 'key'
|
25
|
-
TEXT = <<-TEXT
|
26
|
-
An abstract cache store class. There are multiple cache store implementations, each having its own additional features. See the classes under the ActiveSupport::Cache module, e.g. ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most popular cache store for large production websites.
|
27
|
-
Some implementations may not support all methods beyond the basic cache methods of fetch, write, read, exist?, and delete.
|
28
|
-
ActiveSupport::Cache::Store can store any serializable Ruby object.
|
29
|
-
cache = ActiveSupport::Cache::MemoryStore.new
|
30
|
-
cache.read('city') # => nil
|
31
|
-
cache.write('city', "Duckburgh")
|
32
|
-
cache.read('city') # => "Duckburgh"
|
33
|
-
Keys are always translated into Strings and are case sensitive. When an object is specified as a key and has a cache_key method defined, this method will be called to define the key. Otherwise, the to_param method will be called. Hashes and Arrays can also be used as keys. The elements will be delimited by slashes, and the elements within a Hash will be sorted by key so they are consistent.
|
34
|
-
cache.read('city') == cache.read(:city) # => true
|
35
|
-
Nil values can be cached.
|
36
|
-
If your cache is on a shared infrastructure, you can define a namespace for your cache entries. If a namespace is defined, it will be prefixed on to every key. The namespace can be either a static value or a Proc. If it is a Proc, it will be invoked when each key is evaluated so that you can use application logic to invalidate keys.
|
37
|
-
cache.namespace = -> { @last_mod_time } # Set the namespace to a variable
|
38
|
-
@last_mod_time = Time.now # Invalidate the entire cache by changing namespace
|
39
|
-
Caches can also store values in a compressed format to save space and reduce time spent sending data. Since there is overhead, values must be large enough to warrant compression. To turn on compression either pass compress: true in the initializer or as an option to fetch or write. To specify the threshold at which to compress values, set the :compress_threshold option. The default threshold is 16K.
|
40
|
-
TEXT
|
41
|
-
|
42
|
-
puts 'Compressed Write/Read:'
|
43
|
-
Benchmark.ips do |x|
|
44
|
-
x.report 'readthis:write/read' do
|
45
|
-
readthis.write(KEY, TEXT)
|
46
|
-
readthis.read(KEY)
|
47
|
-
end
|
48
|
-
|
49
|
-
x.report 'dalli:write/read' do
|
50
|
-
dalli.write(KEY, TEXT)
|
51
|
-
dalli.read(KEY)
|
52
|
-
end
|
53
|
-
|
54
|
-
x.compare!
|
55
|
-
end
|
56
|
-
|
57
|
-
puts 'Compressed Read Multi:'
|
58
|
-
MULTI_KEY = (1..30).to_a
|
59
|
-
MULTI_KEY.each do |key|
|
60
|
-
readthis.write(key, TEXT)
|
61
|
-
dalli.write(key, TEXT)
|
62
|
-
end
|
63
|
-
|
64
|
-
Benchmark.ips do |x|
|
65
|
-
x.report 'readthis:read_multi' do
|
66
|
-
readthis.read_multi(*MULTI_KEY)
|
67
|
-
end
|
68
|
-
|
69
|
-
x.report 'dalli:read_multi' do
|
70
|
-
dalli.read_multi(*MULTI_KEY)
|
71
|
-
end
|
72
|
-
|
73
|
-
x.compare!
|
74
|
-
end
|
data/benchmarks/driver.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
Bundler.setup
|
4
|
-
|
5
|
-
require 'benchmark/ips'
|
6
|
-
require 'readthis'
|
7
|
-
|
8
|
-
native = Readthis::Cache.new(redis: { driver: :ruby }, expires_in: 60)
|
9
|
-
hiredis = Readthis::Cache.new(redis: { driver: :hiredis }, expires_in: 60)
|
10
|
-
|
11
|
-
('a'..'z').each { |key| native.write(key, key * 1024) }
|
12
|
-
|
13
|
-
Benchmark.ips do |x|
|
14
|
-
x.report('native:read-multi') { native.read_multi(*('a'..'z')) }
|
15
|
-
x.report('hiredis:read-multi') { hiredis.read_multi(*('a'..'z')) }
|
16
|
-
|
17
|
-
x.compare!
|
18
|
-
end
|
data/benchmarks/generic.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
require 'json'
|
3
|
-
require 'readthis'
|
4
|
-
|
5
|
-
READTHIS = Readthis::Cache.new(
|
6
|
-
expires_in: 120,
|
7
|
-
marshal: JSON,
|
8
|
-
compress: true
|
9
|
-
)
|
10
|
-
|
11
|
-
def write_key(key)
|
12
|
-
READTHIS.write(key, key.to_s * 2048)
|
13
|
-
end
|
14
|
-
|
15
|
-
KEYS = (1..1_000).to_a
|
16
|
-
KEYS.each { |key| write_key(key) }
|
17
|
-
|
18
|
-
Benchmark.ips do |x|
|
19
|
-
x.report 'readthis:write' do
|
20
|
-
write_key(KEYS.sample)
|
21
|
-
end
|
22
|
-
|
23
|
-
x.report 'readthis:read' do
|
24
|
-
READTHIS.read(KEYS.sample)
|
25
|
-
end
|
26
|
-
|
27
|
-
x.report 'readthis:read_multi' do
|
28
|
-
READTHIS.read(KEYS.sample(30))
|
29
|
-
end
|
30
|
-
end
|
data/benchmarks/marshalling.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
Bundler.setup
|
4
|
-
|
5
|
-
require 'benchmark/ips'
|
6
|
-
require 'json'
|
7
|
-
require 'oj'
|
8
|
-
require 'msgpack'
|
9
|
-
require 'readthis'
|
10
|
-
require 'readthis/passthrough'
|
11
|
-
|
12
|
-
Readthis.serializers << Oj
|
13
|
-
Readthis.serializers << MessagePack
|
14
|
-
|
15
|
-
readthis_oj = Readthis::Cache.new(marshal: Oj)
|
16
|
-
readthis_msgpack = Readthis::Cache.new(marshal: MessagePack)
|
17
|
-
readthis_json = Readthis::Cache.new(marshal: JSON)
|
18
|
-
readthis_ruby = Readthis::Cache.new(marshal: Marshal)
|
19
|
-
|
20
|
-
HASH = ('a'..'z').each_with_object({}) { |key, memo| memo[key] = key }
|
21
|
-
|
22
|
-
Benchmark.ips do |x|
|
23
|
-
x.report('oj:hash:dump') { readthis_oj.write('oj', HASH) }
|
24
|
-
x.report('json:hash:dump') { readthis_json.write('json', HASH) }
|
25
|
-
x.report('msgpack:hash:dump') { readthis_msgpack.write('msgpack', HASH) }
|
26
|
-
x.report('ruby:hash:dump') { readthis_ruby.write('ruby', HASH) }
|
27
|
-
|
28
|
-
x.compare!
|
29
|
-
end
|
30
|
-
|
31
|
-
Benchmark.ips do |x|
|
32
|
-
x.report('oj:hash:load') { readthis_oj.read('oj') }
|
33
|
-
x.report('json:hash:load') { readthis_json.read('json') }
|
34
|
-
x.report('msgpack:hash:load') { readthis_msgpack.read('msgpack') }
|
35
|
-
x.report('ruby:hash:load') { readthis_ruby.read('ruby') }
|
36
|
-
|
37
|
-
x.compare!
|
38
|
-
end
|
data/benchmarks/memory.rb
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'bundler'; Bundler.setup
|
2
|
-
a = GC.stat(:total_allocated_objects)
|
3
|
-
|
4
|
-
require 'readthis'
|
5
|
-
b = GC.stat(:total_allocated_objects)
|
6
|
-
|
7
|
-
require 'redis-activesupport'
|
8
|
-
c = GC.stat(:total_allocated_objects)
|
9
|
-
|
10
|
-
puts "readthis: #{b - a}"
|
11
|
-
puts "redis-activesupport: #{c - b}"
|
data/benchmarks/multi.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
require 'dalli'
|
3
|
-
require 'redis-activesupport'
|
4
|
-
require 'active_support/cache/memory_store'
|
5
|
-
require 'active_support/cache/dalli_store'
|
6
|
-
require 'readthis'
|
7
|
-
|
8
|
-
memory = ActiveSupport::Cache::MemoryStore.new(expires_in: 60, namespace: 'mm')
|
9
|
-
dalli = ActiveSupport::Cache::DalliStore.new('localhost', namespace: 'da', pool_size: 5, expires_in: 60)
|
10
|
-
redisas = ActiveSupport::Cache::RedisStore.new('redis://localhost:6379/11/ra', expires_in: 60)
|
11
|
-
readthis = Readthis::Cache.new(namespace: 'rd', expires_in: 60)
|
12
|
-
|
13
|
-
('a'..'z').each do |key|
|
14
|
-
value = key * 1024
|
15
|
-
|
16
|
-
memory.write(key, value)
|
17
|
-
dalli.write(key, value)
|
18
|
-
readthis.write(key, value)
|
19
|
-
redisas.write(key, value)
|
20
|
-
end
|
21
|
-
|
22
|
-
Benchmark.ips do |x|
|
23
|
-
x.report 'memory:read-multi' do
|
24
|
-
memory.read_multi(*('a'..'z'))
|
25
|
-
end
|
26
|
-
|
27
|
-
x.report 'readthis:read-multi' do
|
28
|
-
readthis.read_multi(*('a'..'z'))
|
29
|
-
end
|
30
|
-
|
31
|
-
x.report 'redisas:read-multi' do
|
32
|
-
redisas.read_multi(*('a'..'z'))
|
33
|
-
end
|
34
|
-
|
35
|
-
x.report 'dalli:read-multi' do
|
36
|
-
dalli.read_multi(*('a'..'z'))
|
37
|
-
end
|
38
|
-
|
39
|
-
x.compare!
|
40
|
-
end
|
41
|
-
|
42
|
-
Benchmark.ips do |x|
|
43
|
-
x.report 'memory:fetch-multi' do
|
44
|
-
memory.fetch_multi(*('a'..'z')) { |_| 'missing' }
|
45
|
-
end
|
46
|
-
|
47
|
-
x.report 'readthis:fetch-multi' do
|
48
|
-
readthis.fetch_multi(*('a'..'z')) { |_| 'missing' }
|
49
|
-
end
|
50
|
-
|
51
|
-
x.report 'redisas:fetch-multi' do
|
52
|
-
redisas.fetch_multi(*('a'..'z')) { |_| 'missing' }
|
53
|
-
end
|
54
|
-
|
55
|
-
x.report 'dalli:fetch-multi' do
|
56
|
-
dalli.fetch_multi(*('a'..'z')) { |_| 'missing' }
|
57
|
-
end
|
58
|
-
|
59
|
-
x.compare!
|
60
|
-
end
|
data/benchmarks/parsing.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
|
3
|
-
def parse_a(string)
|
4
|
-
marshal = string[2, 12].strip
|
5
|
-
compress = string[15] == '1'.freeze
|
6
|
-
|
7
|
-
[Kernel.const_get(marshal), compress, string[18..-1]]
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse_b(marked)
|
11
|
-
prefix = marked[0, 32].scrub('*'.freeze)[/R\|(.*)\|R/, 1]
|
12
|
-
offset = prefix.size + 4
|
13
|
-
|
14
|
-
marshal, c_name, _ = prefix.split(' '.freeze)
|
15
|
-
|
16
|
-
compress = c_name == 'true'.freeze
|
17
|
-
|
18
|
-
[Kernel.const_get(marshal), compress, marked[offset..-1]]
|
19
|
-
end
|
20
|
-
|
21
|
-
SERIALIZERS = { Marshal => 0x1 }.freeze
|
22
|
-
DESERIALIZERS = SERIALIZERS.invert.freeze
|
23
|
-
COMPRESSED_FLAG = 0x8
|
24
|
-
MARSHAL_FLAG = 0x3
|
25
|
-
BINARY_FLAG = [SERIALIZERS[Marshal] | COMPRESSED_FLAG].pack('C')
|
26
|
-
|
27
|
-
def parse_c(binary_string)
|
28
|
-
flags = binary_string[0].unpack('C').first
|
29
|
-
|
30
|
-
[DESERIALIZERS[flags & MARSHAL_FLAG], flags & COMPRESSED_FLAG, binary_string[1..-1]]
|
31
|
-
end
|
32
|
-
|
33
|
-
STR = 'R|Marshal 0|Rafdlkadfjadfj asdlkfjasdlfkj asdlfkjdasflkjadsflkjadslkjfadslkjfasdlkjfadlskjf laksdjflkajsdflkjadsflkadjsfladskjf laksjflakdjfalsdkjfadlskjf laksdjflkajdsflk j'
|
34
|
-
STR2 = BINARY_FLAG << 'Rafdlkadfjadfj asdlkfjasdlfkj asdlfkjdasflkjadsflkjadslkjfadslkjfasdlkjfadlskjf laksdjflkajsdflkjadsflkadjsfladskjf laksjflakdjfalsdkjfadlskjf laksdjflkajdsflk j'
|
35
|
-
|
36
|
-
Benchmark.ips do |x|
|
37
|
-
x.report('a') { parse_a(STR) }
|
38
|
-
x.report('b') { parse_b(STR) }
|
39
|
-
x.report('c') { parse_c(STR2) }
|
40
|
-
|
41
|
-
x.compare!
|
42
|
-
end
|
data/benchmarks/profile.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
3
|
-
Bundler.setup
|
4
|
-
|
5
|
-
require 'fileutils'
|
6
|
-
require 'stackprof'
|
7
|
-
require 'readthis'
|
8
|
-
|
9
|
-
readthis = Readthis::Cache.new
|
10
|
-
|
11
|
-
FileUtils.mkdir_p('tmp')
|
12
|
-
readthis.clear
|
13
|
-
|
14
|
-
('a'..'z').each { |key| readthis.write(key, key * 1024) }
|
15
|
-
|
16
|
-
StackProf.run(mode: :object, interval: 500, out: "tmp/stackprof-object.dump") do
|
17
|
-
1000.times do
|
18
|
-
readthis.read_multi(*('a'..'z'))
|
19
|
-
end
|
20
|
-
end
|
data/bin/rspec
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by Bundler.
|
4
|
-
#
|
5
|
-
# The application 'rspec' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
|
-
|
9
|
-
require 'pathname'
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
-
Pathname.new(__FILE__).realpath)
|
12
|
-
|
13
|
-
require 'rubygems'
|
14
|
-
require 'bundler/setup'
|
15
|
-
|
16
|
-
load Gem.bin_path('rspec-core', 'rspec')
|
data/readthis.gemspec
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'readthis/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = 'readthis'
|
8
|
-
spec.version = Readthis::VERSION
|
9
|
-
spec.authors = ['Parker Selbert']
|
10
|
-
spec.email = ['parker@sorentwo.com']
|
11
|
-
spec.summary = 'Pooled active support compliant caching with redis'
|
12
|
-
spec.description = 'Pooled active support compliant caching with redis'
|
13
|
-
spec.homepage = 'https://github.com/sorentwo/readthis'
|
14
|
-
spec.license = 'MIT'
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
-
spec.test_files = spec.files.grep(%r{^(spec)/})
|
18
|
-
spec.require_paths = ['lib']
|
19
|
-
|
20
|
-
spec.add_dependency 'redis', '~> 3.0'
|
21
|
-
spec.add_dependency 'connection_pool', '~> 2.1'
|
22
|
-
|
23
|
-
spec.add_development_dependency 'bundler'
|
24
|
-
spec.add_development_dependency 'hiredis', '~> 0.5'
|
25
|
-
spec.add_development_dependency 'rake'
|
26
|
-
spec.add_development_dependency 'rspec', '~> 3.1'
|
27
|
-
end
|