Last active
January 5, 2024 12:09
-
-
Save vidarh/b72615c16673cb38630cab5148190557 to your computer and use it in GitHub Desktop.
Ruby port of the SIEVE caching algorithm using a ring instead of a linked list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See https://cachemon.github.io/SIEVE-website/blog/2023/12/17/sieve-is-simpler-than-lru/ | |
# for a description and the Python version | |
# *LARGELY UNTESTED* | |
Node = Struct.new(:value, :visited, :prev, :next) | |
class SieveCache | |
def initialize(capacity) | |
@capacity = capacity | |
@cache = {} | |
@hand = @head = Node.new | |
@head.next = @head | |
@head.prev = @head | |
# Yes, this is a dirty trick. | |
def @head.visited = true | |
end | |
def add_to_head(node) | |
node.prev = @head | |
node.next = @head.next | |
@head.next.prev = node | |
@head.next = node | |
end | |
def remove_node(node) | |
node.prev.next = node.next | |
node.next.prev = node.prev | |
end | |
def evict | |
while @hand.visited | |
@hand.visited = false | |
@hand = @hand.prev | |
end | |
@cache.delete(@hand.value) | |
@hand = remove_node(@hand) | |
end | |
def access x | |
if @cache[x] | |
@cache[x].visited = true | |
return | |
end | |
evict if @cache.size == @capacity | |
add_to_head(@cache[x] = Node[x]) | |
end | |
def show_cache | |
current = @head | |
until current.next == @head do | |
current = current.next | |
print "#{current.value} (Visited: #{current.visited ? "True" : "False"})" | |
print " -> " if current.next != @head | |
end | |
puts | |
end | |
end | |
# Example usage | |
cache = SieveCache.new(3) | |
cache.access('A') | |
cache.access('B') | |
cache.access('C') | |
cache.access('D') | |
cache.show_cache() | |
cache.access('C') | |
cache.access('E') | |
cache.show_cache() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See https://cachemon.github.io/SIEVE-website/blog/2023/12/17/sieve-is-simpler-than-lru/ | |
# for a description and the Python version | |
# *LARGELY UNTESTED* | |
# | |
# Single linked list version | |
Node = Struct.new(:value, :visited, :next) | |
class SieveCache | |
def initialize(capacity) | |
@capacity = capacity | |
@cache = {} | |
@prev = @hand = @head = Node.new | |
@head.next = @head | |
# Yes, this is a dirty trick. | |
def @head.visited = true | |
end | |
def add_to_head(node) | |
node.next = @head.next | |
@head.next = node | |
end | |
def evict | |
while @hand.visited | |
@hand.visited = false | |
@prev = @hand | |
@hand = @hand.next | |
end | |
@cache.delete(@hand.value) | |
@hand = @prev.next = @prev.next.next | |
end | |
def access x | |
if @cache[x] | |
@cache[x].visited = true | |
return | |
end | |
evict if @cache.size == @capacity | |
add_to_head(@cache[x] = Node[x]) | |
end | |
def show_cache | |
current = @head | |
until current.next == @head do | |
current = current.next | |
print "#{current.value} (Visited: #{current.visited ? "True" : "False"})" | |
print " -> " if current.next != @head | |
end | |
puts | |
end | |
end | |
# Example usage | |
cache = SieveCache.new(3) | |
cache.access('A') | |
cache.access('B') | |
cache.access('C') | |
cache.access('D') | |
cache.show_cache() | |
cache.access('C') | |
cache.access('E') | |
cache.show_cache() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment