diff --git a/Project.toml b/Project.toml index d395ecf..5b24ff9 100644 --- a/Project.toml +++ b/Project.toml @@ -4,24 +4,21 @@ authors = ["nHackel and contributors"] version = "0.2.0" [deps] +LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637" +RegularizedLeastSquares = "1e9c538a-f78c-5de5-8ffb-0b6dbe892d23" Scratch = "6c6a2e73-6563-6170-7368-637461726353" TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76" ThreadPools = "b189fb0b-2eb5-4ed4-bc0c-d34c51242431" -RegularizedLeastSquares = "1e9c538a-f78c-5de5-8ffb-0b6dbe892d23" [compat] -julia = "1.6" +RegularizedLeastSquares = "0.10, 0.11" Scratch = "1.2" TOML = "1" ThreadPools = "2.1" -RegularizedLeastSquares = "0.10, 0.11" +julia = "1.6" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [targets] test = ["Test"] - - - - diff --git a/src/AbstractImageReconstruction.jl b/src/AbstractImageReconstruction.jl index d27e9c4..5c83414 100644 --- a/src/AbstractImageReconstruction.jl +++ b/src/AbstractImageReconstruction.jl @@ -4,6 +4,7 @@ using TOML using ThreadPools using Scratch using RegularizedLeastSquares +using LRUCache import Base: put!, take!, fieldtypes, fieldtype, ismissing, propertynames, parent, hash diff --git a/src/RecoPlans/Cache.jl b/src/RecoPlans/Cache.jl index 34013c6..415ce7e 100644 --- a/src/RecoPlans/Cache.jl +++ b/src/RecoPlans/Cache.jl @@ -1,32 +1,24 @@ export CachedProcessParameter Base.@kwdef mutable struct CachedProcessParameter{P <: AbstractImageReconstructionParameters} <: AbstractImageReconstructionParameters param::P - cache::Dict{UInt64, Any} = Dict{UInt64, Any}() - lock::ReentrantLock = ReentrantLock() + cache::LRU{UInt64, Any} = LRU{UInt64, Any}(maxsize = maxsize) + const maxsize::Int64 = 1 end function process(algo::AbstractImageReconstructionAlgorithm, param::CachedProcessParameter, inputs...) - lock(param.lock) do - id = hash(param.param, hash(inputs)) - if haskey(param.cache, id) - result = param.cache[id] - else - result = process(algo, param.param, inputs...) - end - param.cache[id] = result - return result + id = hash(param.param, hash(inputs, hash(algo))) + result = get!(param.cache, id) do + process(algo, param.param, inputs...) end + param.cache[id] = result + return result end function process(algo::Type{<:AbstractImageReconstructionAlgorithm}, param::CachedProcessParameter, inputs...) - lock(param.lock) do - id = hash(param.param, hash(inputs)) - if haskey(param.cache, id) - result = param.cache[id] - else - result = process(algo, param.param, inputs...) - end - param.cache[id] = result - return result + id = hash(param.param, hash(inputs, hash(algo))) + result = get!(param.cache, id) do + process(algo, param.param, inputs...) end + param.cache[id] = result + return result end function validvalue(plan, ::Type{T}, value::RecoPlan{<:CachedProcessParameter}) where T @@ -35,26 +27,28 @@ function validvalue(plan, ::Type{T}, value::RecoPlan{<:CachedProcessParameter}) end # Do not serialize cache and lock, only param -addDictValue!(dict, cache::RecoPlan{<:CachedProcessParameter}) = dict["param"] = toDictValue(type(cache, :param), cache.param) +function addDictValue!(dict, cache::RecoPlan{<:CachedProcessParameter}) + size = cache.maxsize + if !ismissing(size) + dict["maxsize"] = size + end + dict["param"] = toDictValue(type(cache, :param), cache.param) +end # When deserializing always construct cache and lock # This means that all algorithms constructed by this plan share lock and cache function loadPlan!(plan::RecoPlan{<:CachedProcessParameter}, dict::Dict{String, Any}, modDict) - cache = Dict{UInt64, Any}() - lock = ReentrantLock() + maxsize = get(dict, "maxsize", 1) + cache = LRU{UInt64, Any}(;maxsize) param = missing if haskey(dict, "param") param = loadPlan!(dict["param"], modDict) end - setvalues!(plan; param, cache, lock) + setvalues!(plan; param, cache, maxsize) return plan end -function Base.empty!(cache::CachedProcessParameter) - lock(cache.lock) do - empty!(cache.cache) - end -end +Base.empty!(cache::CachedProcessParameter) = empty!(cache.cache) """ hash(parameter::AbstractImageReconstructionParameters, h)