Skip to content

Commit

Permalink
Don't evict whole cache for large entries (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericphanson authored Sep 14, 2023
1 parent 6186771 commit cc4d504
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "LRUCache"
uuid = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637"
version = "1.4.1"
version = "1.5.0"

[compat]
julia = "1"
Expand Down
20 changes: 16 additions & 4 deletions src/LRUCache.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,14 @@ function Base.getindex(lru::LRU, key)
end
end
function _unsafe_addindex!(lru::LRU{K}, v, key) where K
s = lru.by(v)::Int
# If entry is larger than entire cache, don't add it
s > lru.maxsize && return
n = LinkedNode{K}(key)
rotate!(_push!(lru.keyset, n))
s = lru.by(v)::Int
lru.currentsize += s
lru.dict[key] = (v, n, s)
return
end
function Base.setindex!(lru::LRU{K, V}, v, key) where {K, V}
evictions = Tuple{K, V}[]
Expand All @@ -162,9 +165,18 @@ function Base.setindex!(lru::LRU{K, V}, v, key) where {K, V}
end
lru.currentsize -= s
s = lru.by(v)::Int
lru.currentsize += s
lru.dict[key] = (v, n, s)
_move_to_front!(lru.keyset, n)
# If new entry is larger than entire cache, don't add it
# (but still evict the old entry!)
if s > lru.maxsize
# We are inside the lock still, so we will remove it manually rather than
# `delete!(lru, key)` which would need the lock again.
delete!(lru.dict, key)
_delete!(lru.keyset, n)
else # add the new entry
lru.currentsize += s
lru.dict[key] = (v, n, s)
_move_to_front!(lru.keyset, n)
end
else
_unsafe_addindex!(lru, v, key)
end
Expand Down
34 changes: 34 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,38 @@ end
@test [k => v for (k,v) in rlru] == ["second" => 2, "third" => 3, "fourth" => 4, "fifth" => 5]
end

# https://github.com/JuliaCollections/LRUCache.jl/issues/37
@testset "Large entries" begin
lru = LRU{Int, Vector{Int}}(; maxsize=10, by=length)
get!(lru, 1, 1:9)
@test !isempty(lru)
@test lru[1] == 1:9

# Add too-big entry
get!(lru, 2, 1:11)
# did not add entry 2, it is too big
@test !haskey(lru, 2)

# Still have old entries
@test !isempty(lru)
@test lru[1] == 1:9

# Same with `setindex!`
lru[2] = 1:11
@test !haskey(lru, 2)
@test !isempty(lru)
@test lru[1] == 1:9

# Add a second small entry
lru[2] = 1:1
@test haskey(lru, 2)
@test lru[1] == 1:9
@test lru[2] == 1:1

# Re-assign it to a too-big entry
lru[2] = 1:11
@test !haskey(lru, 2) # don't keep the old entry!
@test lru[1] == 1:9
end

include("originaltests.jl")

0 comments on commit cc4d504

Please sign in to comment.