Class: Ramaze::LRUHash
- Includes:
- Enumerable
- Defined in:
- lib/ramaze/snippets/ramaze/lru_hash.rb
Overview
A Hash-alike LRU cache that provides fine-grained control over content restrictions.
It allows you to set:
-
a maximum number of elements
-
the maximum amount of memory used for all elements
-
the allowed memory-size per element
-
time to live
Differences to the original implementation include:
-
The Cache is now a Struct for speed
-
Object memory size is obtained via Marshal::dump instead of #to_s
Note that due to calculating object size with Marshal, you might have to do some evaluation as to how large your values will be when marshaled, for example a String will have String#size + 10. This differs from object to object and between versions of Marshal, so be generous.
Copyright © 2002 Yoshinori K. Okuji <[email protected]> Copyright © 2009 Michael Fellinger <[email protected]>
You may redistribute it and/or modify it under the same terms as Ruby.
Defined Under Namespace
Classes: CacheObject
Constant Summary collapse
- VERSION =
'0.3'
- KeyError =
On 1.8 we raise IndexError, on 1.9 we raise KeyError
Module.const_defined?(:KeyError) ? KeyError : IndexError
Instance Attribute Summary collapse
-
#expiration ⇒ Object
Returns the value of attribute expiration.
-
#hits ⇒ Object
Returns the value of attribute hits.
-
#hook ⇒ Object
Returns the value of attribute hook.
-
#list ⇒ Object
Returns the value of attribute list.
-
#max_count ⇒ Object
Returns the value of attribute max_count.
-
#max_total ⇒ Object
Returns the value of attribute max_total.
-
#max_value ⇒ Object
Returns the value of attribute max_value.
-
#misses ⇒ Object
Returns the value of attribute misses.
-
#objs ⇒ Object
Returns the value of attribute objs.
-
#total_size ⇒ Object
Returns the value of attribute total_size.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #[]=(key, obj) ⇒ Object
- #clear ⇒ Object (also: #invalidate_all)
- #delete(key) ⇒ Object (also: #invalidate)
- #each_key(&block) ⇒ Object
- #each_pair ⇒ Object
- #each_value ⇒ Object
- #empty? ⇒ Boolean
- #expire ⇒ Object
-
#fetch(key, default = (p_default = true; nil)) ⇒ Object
Note that this method diverges from the default behaviour of the Ruby Hash.
- #index(given_value) ⇒ Object
-
#initialize(options = {}, &hook) ⇒ LRUHash
constructor
A new instance of LRUHash.
- #key?(key) ⇒ Boolean
- #keys ⇒ Object
- #size ⇒ Object (also: #length)
- #statistics ⇒ Object
- #store(key, value) ⇒ Object
- #to_hash ⇒ Object
- #value?(given_value) ⇒ Boolean
- #values ⇒ Object
Methods inherited from Struct
Constructor Details
#initialize(options = {}, &hook) ⇒ LRUHash
Returns a new instance of LRUHash.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 35 def initialize( = {}, &hook) self.max_value = [:max_value] self.max_total = [:max_total] self.max_count = [:max_count] self.expiration = [:expiration] self.hook = hook self.objs = {} self.list = [] self.total_size = 0 self.hits = self.misses = 0 end |
Instance Attribute Details
#expiration ⇒ Object
Returns the value of attribute expiration
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def expiration @expiration end |
#hits ⇒ Object
Returns the value of attribute hits
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def hits @hits end |
#hook ⇒ Object
Returns the value of attribute hook
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def hook @hook end |
#list ⇒ Object
Returns the value of attribute list
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def list @list end |
#max_count ⇒ Object
Returns the value of attribute max_count
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def max_count @max_count end |
#max_total ⇒ Object
Returns the value of attribute max_total
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def max_total @max_total end |
#max_value ⇒ Object
Returns the value of attribute max_value
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def max_value @max_value end |
#misses ⇒ Object
Returns the value of attribute misses
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def misses @misses end |
#objs ⇒ Object
Returns the value of attribute objs
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def objs @objs end |
#total_size ⇒ Object
Returns the value of attribute total_size
25 26 27 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 25 def total_size @total_size end |
Instance Method Details
#[](key) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 121 def [](key) expire unless objs.key?(key) self.misses += 1 return end obj = objs[key] obj.atime = Time.now.to_i list.delete_if{|list_key| key == list_key } list << key self.hits += 1 obj.content end |
#[]=(key, obj) ⇒ Object
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 139 def []=(key, obj) expire invalidate key if key?(key) size = Marshal.dump(obj).size if max_value && max_value < max_total warn "%p isn't cached because it exceeds max_value %p" % [obj, max_value] return obj end if max_value.nil? && max_total && max_total < size warn "%p isn't cached because it exceeds max_total: %p" % [obj, max_total] return obj end invalidate list.first if max_count && max_count == list.size self.total_size += size if max_total invalidate list.first until total_size < max_total end objs[key] = CacheObject.new(obj, size, Time.now.to_i) list << key obj end |
#clear ⇒ Object Also known as: invalidate_all
103 104 105 106 107 108 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 103 def clear objs.each{|key, obj| hook.call(key, obj) } if hook objs.clear list.clear self.total_size = 0 end |
#delete(key) ⇒ Object Also known as: invalidate
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 89 def delete(key) return unless objs.key?(key) obj = objs[key] hook.call(key, obj.content) if hook self.total_size -= obj.size objs.delete key list.delete_if{|list_key| key == list_key } obj.content end |
#each_key(&block) ⇒ Object
180 181 182 183 184 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 180 def each_key(&block) return enum_for(:each_key) unless block_given? objs.each_key{|key| yield key } self end |
#each_pair ⇒ Object
174 175 176 177 178 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 174 def each_pair return enum_for(:each_pair) unless block_given? objs.each{|key, obj| yield key, obj.content } self end |
#each_value ⇒ Object
186 187 188 189 190 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 186 def each_value return enum_for(:each_value) unless block_given? objs.each_value{|obj| yield obj.content } self end |
#empty? ⇒ Boolean
192 193 194 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 192 def empty? objs.empty? end |
#expire ⇒ Object
111 112 113 114 115 116 117 118 119 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 111 def expire return unless expiration now = Time.now.to_i list.each_with_index do |key, index| break unless (objs[key].atime + expiration) <= now invalidate key end end |
#fetch(key, default = (p_default = true; nil)) ⇒ Object
Note that this method diverges from the default behaviour of the Ruby Hash. If the cache doesn’t find content for the given key, it will store the given default instead. Optionally it also takes a block, the return value of the block is then stored and returned.
209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 209 def fetch(key, default = (p_default = true; nil)) if key?(key) value = self[key] elsif p_default.nil? value = self[key] = default elsif block_given? value = self[key] = yield(key) else raise KeyError, "key not found: %p" % [key] end value end |
#index(given_value) ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 64 def index(given_value) objs.each do |key, obj| return key if given_value == obj.content end nil end |
#key?(key) ⇒ Boolean
52 53 54 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 52 def key?(key) objs.key?(key) end |
#keys ⇒ Object
72 73 74 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 72 def keys objs.keys end |
#size ⇒ Object Also known as: length
76 77 78 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 76 def size objs.size end |
#statistics ⇒ Object
223 224 225 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 223 def statistics {:size => total_size, :count => list.size, :hits => hits, :misses => misses} end |
#store(key, value) ⇒ Object
170 171 172 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 170 def store(key, value) self[key] = value end |
#to_hash ⇒ Object
81 82 83 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 81 def to_hash objs.dup end |
#value?(given_value) ⇒ Boolean
56 57 58 59 60 61 62 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 56 def value?(given_value) objs.each do |key, obj| return true if given_value == obj.content end false end |
#values ⇒ Object
85 86 87 |
# File 'lib/ramaze/snippets/ramaze/lru_hash.rb', line 85 def values objs.map{|key, obj| obj.content } end |