maximerischard / LRUCache.jl

An implementation of an LRU Cache in Julia

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LRUCache.jl

Build Status

Provides an implementation of a Least Recently Used (LRU) Cache for Julia.

An LRU Cache is a useful associative data structure that has a set maximum size. Once that size is reached, the least recently used items are removed first.

Interface

LRU supports the standard Associative interface. Some examples of common operations are shown below:

Creation

lru = LRU{K, V}([, maxsize=100])

Create an LRU Cache with maximum size maxsize. If maxsize is not provided, a default of 100 is used.

Add an item to the cache

setitem!(lru, key, value)
lru[key] = value

Lookup an item in the cache

getitem(lru, key)
lru[key]

Change the maxsize

resize!(lru, size)

Empty the cache

empty!(lru)

Caching Use

To effectively use LRU as a cache, several functions and macros have been defined that allow for easy checking if an item is present, and if not quickly calculating a default.

get!(lru::LRU, key, default)

Returns the value stored in lru for key if present. If not, stores key => default, and returns default.

get!(default::Callable, lru::LRU, key)

Like above, except if key is not present, stores key => default(), and returns the result. This is intended to be used in do block syntax:

get!(lru, key) do
   ...
end

@get!(lru::LRU, key, default)

The do block syntax of get! is nice, but can be slow due to how Julia currently handles anonymous functions. The @get! macro is an attempt to get around this issue. It takes 3 parameters: the cache, a key to lookup, and a default. Note that as this is handled with meta-programming, the default can be anything that can be set as the right-hand-side of an assignment. Example.

const lru = LRU{Float64, Int}()

_foo(a::Float64) = ...    # Some long-running calculation that returns an Int

function foo(a::Float64)
    @get! lru a _foo(a)
end

This expands (roughly) to:

function foo(a::Float64)
    return begin
        if haskey(lru, a)
            value = lru[a]
        else
            value = _foo(a)
            lru[a] = value
        end
        value
    end
end

The same can be done with a constant default value, or a begin block:

const lru = LRU{Int, Int}()

function fib(a::Int)
    @get! lru a begin
        if a < 2
            a
        else
            fib(a - 1) + fib(a - 2)
        end
    end
end

Example

Commonly, you may have some long running function that sometimes gets called with the same parameters more than once. As such, it may benefit from cacheing the results.

Here's our example, long running calculation:

function foo(a::Float64, b::Float64)
    sleep(100)
    result = a * b
end

As this function requires more than one parameter, we need a cache from (Float64, Float64) to Float64. A cached version is then:

const lru = LRU{(Float64, Float64), Float64}()

function cached_foo(a::Float64, b::Float64)
    @get! lru (a, b) foo(a, b)
end

About

An implementation of an LRU Cache in Julia

License:Other


Languages

Language:Julia 100.0%