[ANN] Caching.jl, yet another memoizer with more features

Caching.jl aims to provide a simple non-intrusive memoization mechanism with disk, compression, record and size limits support. While it’s not the fastest, it should pretty easy to use, understand and extend. It is still lacking in the documentation area however the examples provided in the package page cover most of the functionality.

Just for the record, a list of memoization packages I encountered so far in the Julia ecosystem (lots of good ideas in all for whomever is interested):

7 Likes

When your cache is full, how do you decide which entry to throw out?

Do you throw out
(1) Random entry
(2) Least Recently Used entry
(3) Oldest (by creation timestamp) entry

1 Like

(3) but not by timestamp, simply by call order; the history is preserved in a Deque. It the cache is full, the deque’s head is popped :wink: (/src/cache.jl, line 131)

2 Likes

Hey! First of all, congratulations, this is a pretty useful package! Yet, I’m still facing a problem when trying to use the caching to keep data on disk. I’m using this to store a specific variable I need to use in a Dash app.

using Dash, Caching

app = dash()

app.layout = #some code here

cache = @cache mem = x::Int -> x "cache_file.bin"

callback!(
        app,
        Output("dummy", "children"),
        Input("dados", "data")
    ) do dado_usuario
        pesquisas = jsontable(dado_usuario) |> DataFrame

        # Taking the greatest value of variable id_pesquisa
        # and caching it
        cache(isa(maximum(pesquisas.id_pesquisa), MethodError) ? 0 : maximum(pesquisas.id_pesquisa))
        @persist! cache

        return 0
    end

@syncache! cache "disk"

# I just want the last value, so I take the last array's element
n = collect(values(cache.cache))[end]

# Do some stuff n times
for itr in 1:n
    ...
end

I know I may be getting something wrong about the scope of the variables, but I thought that as long as I synced the cache variable, it would not be a problem.

Any ideas on how can I use the caching correctly in this case?

Hi, I am having a bit of trouble understanding your issue.

From what I can see in the code, collecting the values from cache.cache does not guarantee that the last value is the last in any way (dictionaries are not ordered so, when collecting values, the order does not make any sense).

If you want the last value written you should

  • store the last key (i.e. cache input argument), return it with callback! and call cache(last_value);
    or,
  • more dangerously, load the value from the addresses specified in cache.offsets (if using just persist, the file just grows incremetally with each stored entry and the order of calls is implicitly preserved).