Class: Fontisan::Variation::Cache
- Inherits:
-
Object
- Object
- Fontisan::Variation::Cache
- Defined in:
- lib/fontisan/variation/cache.rb
Overview
Caches variation calculations for performance
This class implements a caching layer for expensive variation calculations to significantly improve instance generation performance. It caches:
-
Normalized scalars per coordinate set
-
Interpolated values
-
Instance generation results
-
Region matches
Cache strategies:
-
LRU (Least Recently Used) for memory management
-
Coordinate-based keys for scalar caching
-
Invalidation on font modification
-
Optional persistent caching across sessions
Direct Known Subclasses
Instance Attribute Summary collapse
-
#max_size ⇒ Integer
readonly
Maximum cache size.
-
#stats ⇒ Hash
readonly
Cache statistics.
Instance Method Summary collapse
-
#cached?(key) ⇒ Boolean
Check if key is cached and valid.
-
#clear ⇒ Object
Clear entire cache.
-
#empty? ⇒ Boolean
Check if cache is empty.
-
#fetch(key) { ... } ⇒ Object
Generic fetch with caching.
-
#fetch_instance(font_checksum, coordinates) { ... } ⇒ Hash
Fetch or compute instance generation result.
-
#fetch_interpolated(base_value, deltas, scalars) { ... } ⇒ Float
Fetch or compute interpolated value.
-
#fetch_region_matches(coordinates, regions) { ... } ⇒ Array
Fetch or compute region matches.
-
#fetch_scalars(coordinates, axes) { ... } ⇒ Array<Float>
Fetch or compute scalars for coordinates.
-
#full? ⇒ Boolean
Check if cache is full.
-
#initialize(max_size: 1000, ttl: nil) ⇒ Cache
constructor
Initialize cache.
-
#invalidate(key) ⇒ Object
Invalidate specific key.
-
#invalidate_matching(pattern) ⇒ Object
Invalidate keys matching pattern.
-
#size ⇒ Integer
Get cache size.
-
#statistics ⇒ Hash
Get cache statistics.
-
#store(key, value) ⇒ Object
Store value in cache.
Constructor Details
#initialize(max_size: 1000, ttl: nil) ⇒ Cache
Initialize cache
42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/fontisan/variation/cache.rb', line 42 def initialize(max_size: 1000, ttl: nil) @max_size = max_size @ttl = ttl @cache = {} @access_times = {} @access_counter = 0 @stats = { hits: 0, misses: 0, evictions: 0, invalidations: 0, } end |
Instance Attribute Details
#max_size ⇒ Integer (readonly)
Returns Maximum cache size.
33 34 35 |
# File 'lib/fontisan/variation/cache.rb', line 33 def max_size @max_size end |
#stats ⇒ Hash (readonly)
Returns Cache statistics.
36 37 38 |
# File 'lib/fontisan/variation/cache.rb', line 36 def stats @stats end |
Instance Method Details
#cached?(key) ⇒ Boolean
Check if key is cached and valid
123 124 125 126 127 128 |
# File 'lib/fontisan/variation/cache.rb', line 123 def cached?(key) return false unless @cache.key?(key) return false if expired?(key) true end |
#clear ⇒ Object
Clear entire cache
145 146 147 148 149 |
# File 'lib/fontisan/variation/cache.rb', line 145 def clear @cache.clear @access_times.clear @stats[:invalidations] += 1 end |
#empty? ⇒ Boolean
Check if cache is empty
193 194 195 |
# File 'lib/fontisan/variation/cache.rb', line 193 def empty? @cache.empty? end |
#fetch(key) { ... } ⇒ Object
Generic fetch with caching
106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/fontisan/variation/cache.rb', line 106 def fetch(key) if cached?(key) @stats[:hits] += 1 touch(key) return @cache[key][:value] end @stats[:misses] += 1 value = yield store(key, value) value end |
#fetch_instance(font_checksum, coordinates) { ... } ⇒ Hash
Fetch or compute instance generation result
85 86 87 88 |
# File 'lib/fontisan/variation/cache.rb', line 85 def fetch_instance(font_checksum, coordinates, &) key = CacheKeyBuilder.instance_key(font_checksum, coordinates) fetch(key, &) end |
#fetch_interpolated(base_value, deltas, scalars) { ... } ⇒ Float
Fetch or compute interpolated value
74 75 76 77 |
# File 'lib/fontisan/variation/cache.rb', line 74 def fetch_interpolated(base_value, deltas, scalars, &) key = CacheKeyBuilder.interpolation_key(base_value, deltas, scalars) fetch(key, &) end |
#fetch_region_matches(coordinates, regions) { ... } ⇒ Array
Fetch or compute region matches
96 97 98 99 |
# File 'lib/fontisan/variation/cache.rb', line 96 def fetch_region_matches(coordinates, regions, &) key = CacheKeyBuilder.region_matches_key(coordinates, regions) fetch(key, &) end |
#fetch_scalars(coordinates, axes) { ... } ⇒ Array<Float>
Fetch or compute scalars for coordinates
62 63 64 65 |
# File 'lib/fontisan/variation/cache.rb', line 62 def fetch_scalars(coordinates, axes, &) key = CacheKeyBuilder.scalars_key(coordinates, axes) fetch(key, &) end |
#full? ⇒ Boolean
Check if cache is full
200 201 202 |
# File 'lib/fontisan/variation/cache.rb', line 200 def full? @cache.size >= @max_size end |
#invalidate(key) ⇒ Object
Invalidate specific key
154 155 156 157 158 |
# File 'lib/fontisan/variation/cache.rb', line 154 def invalidate(key) @cache.delete(key) @access_times.delete(key) @stats[:invalidations] += 1 end |
#invalidate_matching(pattern) ⇒ Object
Invalidate keys matching pattern
163 164 165 166 |
# File 'lib/fontisan/variation/cache.rb', line 163 def invalidate_matching(pattern) keys = @cache.keys.select { |k| k.match?(pattern) } keys.each { |k| invalidate(k) } end |
#size ⇒ Integer
Get cache size
186 187 188 |
# File 'lib/fontisan/variation/cache.rb', line 186 def size @cache.size end |
#statistics ⇒ Hash
Get cache statistics
171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/fontisan/variation/cache.rb', line 171 def statistics total = @stats[:hits] + @stats[:misses] hit_rate = total.zero? ? 0.0 : @stats[:hits].to_f / total @stats.merge( total_requests: total, hit_rate: hit_rate, size: @cache.size, max_size: @max_size, ) end |
#store(key, value) ⇒ Object
Store value in cache
134 135 136 137 138 139 140 141 142 |
# File 'lib/fontisan/variation/cache.rb', line 134 def store(key, value) evict_if_needed @cache[key] = { value: value, created_at: Time.now, } touch(key) end |