@ -14,10 +14,16 @@ end
local Cache = {
-- Cache configuration:
-- Max storage space, in bytes
size = 8 * 1024 * 1024 ,
-- Average item size is used to compute the amount of slots in the LRU
avg_itemsize = 8196 ,
-- Max storage space, in bytes...
size = nil ,
-- ...Average item size, used to compute the amount of slots in the LRU.
avg_itemsize = nil ,
-- Or, simply set the number of slots, with no storage space limitation.
-- c.f., GlyphCache, CatalogCache
slots = nil ,
-- Should LRU call the object's onFree method on eviction? Implies using CacheItem instead of plain tables/objects.
-- c.f., DocCache
enable_eviction_cb = false ,
-- Generally, only DocCache uses this
disk_cache = false ,
cache_path = nil ,
@ -32,9 +38,14 @@ function Cache:new(o)
end
function Cache : init ( )
if self.slots then
-- Caller doesn't care about storage space, just slot count
self.cache = lru.new ( self.slots , nil , self.enable_eviction_cb )
else
-- Compute the amount of slots in the LRU based on the max size & the average item size
self.slots = math.floor ( self.size / self.avg_itemsize )
self.cache = lru.new ( self.slots , self.size )
self.cache = lru.new ( self.slots , self.size , self.enable_eviction_cb )
end
if self.disk_cache then
self.cached = self : _getDiskCache ( )
@ -42,6 +53,15 @@ function Cache:init()
-- No need to go through our own check or even get methods if there's no disk cache, hit lru directly
self.check = self.cache . get
end
if not self.enable_eviction_cb or not self.size then
-- We won't be using CacheItem here, so we can pass the size manually if necessary.
-- e.g., insert's signature is now (key, value, [size]), instead of relying on CacheItem's size field.
self.insert = self.cache . set
-- With debug info (c.f., below)
--self.insert = self.set
end
end
--[[
@ -157,14 +177,25 @@ function Cache:insert(key, object)
self.cache : set ( key , object , object.size )
-- Accounting debugging
--[[
--self:_insertion_stats(key, object.size)
end
--[[
function Cache : set ( key , object , size )
self.cache : set ( key , object , size )
-- Accounting debugging
self : _insertion_stats ( key , size )
end
function Cache : _insertion_stats ( key , size )
print ( string.format ( " Cache %s (%d/%d) [%.2f/%.2f @ ~%db] inserted %db key: %s " ,
self ,
self.cache : used_slots ( ) , self.slots , self.cache : used_size ( ) / 1024 / 1024 ,
self.size / 1024 / 1024 , self.cache : used_size ( ) / self.cache : used_slots ( ) ,
object.size , key ) )
--]]
self.cache : used_slots ( ) , self.slots ,
self.cache : used_size ( ) / 1024 / 1024 , ( self.size or 0 ) / 1024 / 1024 , self.cache : used_size ( ) / self.cache : used_slots ( ) ,
size or 0 , key ) )
end
--]]
--[[
-- check for cache item by key
@ -275,8 +306,10 @@ function Cache:memoryPressureCheck()
end
-- If less that 20% of the total RAM is free, drop half the Cache...
if memfree / memtotal < 0.20 then
logger.warn ( " Running low on memory, evicting half of the cache... " )
local free_fraction = memfree / memtotal
if free_fraction < 0.20 then
logger.warn ( string.format ( " Running low on memory (~%d%%, ~%.2f/%d MiB), evicting half of the cache... " ,
free_fraction * 100 , memfree / 1024 / 1024 , memtotal / 1024 / 1024 ) )
self.cache : chop ( )
-- And finish by forcing a GC sweep now...