lru_redux 0.0.4 → 0.0.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.
- checksums.yaml +4 -4
- data/README.md +34 -14
- data/lib/lru_redux.rb +12 -2
- data/lib/lru_redux/cache.rb +22 -0
- data/lib/lru_redux/cache19.rb +88 -0
- data/lib/lru_redux/thread_safe_cache.rb +1 -1
- data/lib/lru_redux/version.rb +1 -1
- data/test/cache_test.rb +19 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3f0297d9fe3517fc8618150089f1fd9c7be2e52
|
4
|
+
data.tar.gz: fe4b97bb0935477011f09063e4e5372a3ff88f8a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 955339b2b777e904ac433848202155590815863804f71e48ff78f1f8077c365bada7dcc4a4050301c482a1d21e96ec28165b2bb1b817966da4d539e281df65a7
|
7
|
+
data.tar.gz: adde05c954aa10c9c708c64d06787aff921e883b92400e736a3027452cd327b6b47dea3da0c6af069567e10ffb7a7d5ca56bb125a720ecd22cbbc2dde4a59c03
|
data/README.md
CHANGED
@@ -26,9 +26,14 @@ Or install it yourself as:
|
|
26
26
|
require 'lru_redux'
|
27
27
|
|
28
28
|
# non thread safe
|
29
|
-
cache = LruRedux::Cache(100)
|
29
|
+
cache = LruRedux::Cache.new(100)
|
30
30
|
cache[:a] = "1"
|
31
31
|
cache[:b] = "2"
|
32
|
+
|
33
|
+
cache.to_a
|
34
|
+
# [[:b,"2"],[:a,"1"]]
|
35
|
+
# note the order matters here, last accessed is first
|
36
|
+
|
32
37
|
cache[:a] # a pushed to front
|
33
38
|
# "1"
|
34
39
|
|
@@ -36,10 +41,20 @@ cache.to_a
|
|
36
41
|
# [[:a,"1"],[:b,"2"]]
|
37
42
|
cache.delete(:a)
|
38
43
|
cache.each {|k,v| p "#{k} #{v}"}
|
39
|
-
#
|
44
|
+
# b 2
|
45
|
+
|
40
46
|
cache.max_size(200) # cache now stores 200 items
|
41
47
|
cache.clear # cache has no items
|
42
48
|
|
49
|
+
cache.getset(:a){1}
|
50
|
+
cache.to_a
|
51
|
+
#[[:a,1]]
|
52
|
+
|
53
|
+
# already set so don't call block
|
54
|
+
cache.getset(:a){99}
|
55
|
+
cache.to_a
|
56
|
+
#[[:a,1]]
|
57
|
+
|
43
58
|
# for thread safe access, all methods on cache
|
44
59
|
# are protected with a mutex
|
45
60
|
cache = LruRedux::ThreadSafeCache(100)
|
@@ -48,24 +63,24 @@ cache = LruRedux::ThreadSafeCache(100)
|
|
48
63
|
|
49
64
|
## Benchmarks
|
50
65
|
|
51
|
-
see: benchmark directory
|
66
|
+
see: benchmark directory (a million random lookup / store)
|
52
67
|
|
53
68
|
```
|
54
69
|
sam@ubuntu:~/Source/lru_redux/bench$ ruby ./bench.rb
|
55
70
|
Rehearsal ---------------------------------------------------------
|
56
|
-
thread safe lru 27.
|
57
|
-
lru gem 2.
|
58
|
-
lru_cache gem
|
59
|
-
lru_redux gem 1.
|
60
|
-
lru_redux thread safe 2.
|
61
|
-
----------------------------------------------- total:
|
71
|
+
thread safe lru 27.940000 0.020000 27.960000 ( 28.026869)
|
72
|
+
lru gem 2.250000 0.010000 2.260000 ( 2.256652)
|
73
|
+
lru_cache gem 1.980000 0.000000 1.980000 ( 1.979244)
|
74
|
+
lru_redux gem 1.190000 0.000000 1.190000 ( 1.187640)
|
75
|
+
lru_redux thread safe 2.480000 0.000000 2.480000 ( 2.486314)
|
76
|
+
----------------------------------------------- total: 35.870000sec
|
62
77
|
|
63
78
|
user system total real
|
64
|
-
thread safe lru 28.
|
65
|
-
lru gem 2.
|
66
|
-
lru_cache gem
|
67
|
-
lru_redux gem 1.
|
68
|
-
lru_redux thread safe 2.
|
79
|
+
thread safe lru 28.010000 0.000000 28.010000 ( 28.023534)
|
80
|
+
lru gem 2.250000 0.000000 2.250000 ( 2.256425)
|
81
|
+
lru_cache gem 1.920000 0.000000 1.920000 ( 1.925362)
|
82
|
+
lru_redux gem 1.170000 0.000000 1.170000 ( 1.170970)
|
83
|
+
lru_redux thread safe 2.480000 0.000000 2.480000 ( 2.488169)
|
69
84
|
|
70
85
|
```
|
71
86
|
|
@@ -80,6 +95,11 @@ lru_redux thread safe 2.590000 0.000000 2.590000 ( 2.600422)
|
|
80
95
|
|
81
96
|
## Changlog
|
82
97
|
|
98
|
+
###version 0.0.5 - 23-April-2013
|
99
|
+
|
100
|
+
- Added getset and fetch
|
101
|
+
- Optimised implementation so it 20-30% faster on Ruby 1.9+
|
102
|
+
|
83
103
|
###version 0.0.4 - 23-April-2013
|
84
104
|
|
85
105
|
- Initial version
|
data/lib/lru_redux.rb
CHANGED
@@ -1,4 +1,14 @@
|
|
1
|
-
module LruRedux
|
1
|
+
module LruRedux
|
2
|
+
def self.is_19?
|
3
|
+
major,minor = RUBY_VERSION.split(".").map{|a| a.to_i}
|
4
|
+
major > 1 || (major == 1 && minor > 8)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
2
8
|
require "lru_redux/version"
|
3
|
-
|
9
|
+
if LruRedux.is_19?
|
10
|
+
require "lru_redux/cache19"
|
11
|
+
else
|
12
|
+
require "lru_redux/cache"
|
13
|
+
end
|
4
14
|
require "lru_redux/thread_safe_cache"
|
data/lib/lru_redux/cache.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
|
2
|
+
|
1
3
|
class LruRedux::Cache
|
2
4
|
|
3
5
|
# for high efficiency nodes in double linked list are stored in arrays
|
@@ -20,6 +22,26 @@ class LruRedux::Cache
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
def getset(key)
|
26
|
+
node = @data[key]
|
27
|
+
if node
|
28
|
+
move_to_head(node)
|
29
|
+
node[2]
|
30
|
+
else
|
31
|
+
self[key] = yield
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetch(key)
|
36
|
+
node = @data[key]
|
37
|
+
if node
|
38
|
+
move_to_head(node)
|
39
|
+
node[2]
|
40
|
+
else
|
41
|
+
yield if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
23
45
|
def [](key)
|
24
46
|
node = @data[key]
|
25
47
|
if node
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Ruby 1.9 makes our life easier, Hash is already ordered
|
2
|
+
#
|
3
|
+
# This is an ultra efficient 1.9 freindly implementation
|
4
|
+
class LruRedux::Cache
|
5
|
+
def initialize(max_size)
|
6
|
+
@max_size = max_size
|
7
|
+
@data = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def max_size=(size)
|
11
|
+
raise ArgumentError.new(:max_size) if @max_size < 1
|
12
|
+
@max_size = size
|
13
|
+
if @max_size < @data.size
|
14
|
+
@data.keys[0..@max_size-@data.size].each do |k|
|
15
|
+
@data.delete(k)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def getset(key)
|
21
|
+
found = true
|
22
|
+
value = @data.delete(key){ found = false }
|
23
|
+
if found
|
24
|
+
@data[key] = value
|
25
|
+
else
|
26
|
+
@data[key] = yield
|
27
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def fetch(key)
|
32
|
+
found = true
|
33
|
+
value = @data.delete(key){ found = false }
|
34
|
+
if found
|
35
|
+
@data[key] = value
|
36
|
+
else
|
37
|
+
yield if block_given?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def [](key)
|
42
|
+
found = true
|
43
|
+
value = @data.delete(key){ found = false }
|
44
|
+
if found
|
45
|
+
@data[key] = value
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def []=(key,val)
|
52
|
+
@data.delete(key)
|
53
|
+
@data[key] = val
|
54
|
+
@data.delete(@data.first[0]) if @data.length > @max_size
|
55
|
+
val
|
56
|
+
end
|
57
|
+
|
58
|
+
def each
|
59
|
+
@data.reverse.each do |pair|
|
60
|
+
yield pair
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# used further up the chain, non thread safe each
|
65
|
+
alias_method :each_unsafe, :each
|
66
|
+
|
67
|
+
def to_a
|
68
|
+
@data.to_a.reverse
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(k)
|
72
|
+
@data.delete(k)
|
73
|
+
end
|
74
|
+
|
75
|
+
def clear
|
76
|
+
@data.clear
|
77
|
+
end
|
78
|
+
|
79
|
+
def count
|
80
|
+
@data.count
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# for cache validation only, ensures all is sound
|
85
|
+
def valid?
|
86
|
+
true
|
87
|
+
end
|
88
|
+
end
|
data/lib/lru_redux/version.rb
CHANGED
data/test/cache_test.rb
CHANGED
@@ -21,6 +21,25 @@ class CacheTest < MiniTest::Unit::TestCase
|
|
21
21
|
assert_nil @c[:a]
|
22
22
|
end
|
23
23
|
|
24
|
+
def test_fetch
|
25
|
+
@c[:a] = nil
|
26
|
+
@c[:b] = 2
|
27
|
+
assert_equal @c.fetch(:a){1}, nil
|
28
|
+
assert_equal @c.fetch(:c){3}, 3
|
29
|
+
|
30
|
+
assert_equal [[:a,nil],[:b,2]], @c.to_a
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_getset
|
34
|
+
@c.getset(:a){1}
|
35
|
+
@c.getset(:b){2}
|
36
|
+
assert_equal @c.getset(:a){11}, 1
|
37
|
+
@c.getset(:c){3}
|
38
|
+
@c.getset(:d){4}
|
39
|
+
|
40
|
+
assert_equal [[:d,4],[:c,3],[:a,1]], @c.to_a
|
41
|
+
end
|
42
|
+
|
24
43
|
def test_pushes_lru_to_back
|
25
44
|
@c[:a] = 1
|
26
45
|
@c[:b] = 2
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lru_redux
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- bench/bench.rb
|
111
111
|
- lib/lru_redux.rb
|
112
112
|
- lib/lru_redux/cache.rb
|
113
|
+
- lib/lru_redux/cache19.rb
|
113
114
|
- lib/lru_redux/thread_safe_cache.rb
|
114
115
|
- lib/lru_redux/version.rb
|
115
116
|
- lru_redux.gemspec
|
@@ -135,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
136
|
version: '0'
|
136
137
|
requirements: []
|
137
138
|
rubyforge_project:
|
138
|
-
rubygems_version: 2.0.
|
139
|
+
rubygems_version: 2.0.0.rc.2
|
139
140
|
signing_key:
|
140
141
|
specification_version: 4
|
141
142
|
summary: An efficient implementation of an lru cache
|