An Dict like LRU container which also has ttl feature.
Project description
LRU Dict
A fixed size dict like container which support ttl and evicts Least Recently Used (LRU) items once size limit is exceeded or the ttl is exceeded. LRU maximum capacity can be modified at run-time.
This is a project forked from https://github.com/amitdev/lru-dict and I added ttl feature for it which makes it more suitable to be a cache. If you want to know more about the origin work, please go to the above url.
Install
pip install ttlru-dict
or
easy_install ttlru_dict
Usage
This can be used to build a LRU cache with TTL. Usage is almost like a dict.
from ttlru import TTLRU
import time
# Create an TTLRU container that can hold 5 items, with default ttl = 1s
# *NOTE* ttl is represented in nanoseconds
l = TTLRU(5, ttl=1*1000000000)
# add an item with a default ttl, in this case, it's 1000000000ns = 1 second
l[0] = '0'
# add an item with specified ttl, in this case it's 2 seconds
l.set_with_ttl(1, '1', 2*1000000000)
print(l.items())
# Would print [(1, '1'), (0, '0')]
time.sleep(1)
print(l.items())
# Would print [(1, '1')], the first item expired.
time.sleep(1)
print(l.items())
# Would print [], the second item also expired after 2 seconds.
# ===================================================================
# orher operations without ttl
l = TTLRU(5)
print(l.peek_first_item(), l.peek_last_item()) #return the MRU key and LRU key
# Would print None None
for i in range(5):
l[i] = str(i)
print(l.items()) # Prints items in MRU order
# Would print [(4, '4'), (3, '3'), (2, '2'), (1, '1'), (0, '0')]
print(l.peek_first_item(), l.peek_last_item()) #return the MRU key and LRU key
# Would print (4, '4') (0, '0')
l[5] = '5' # Inserting one more item should evict the old item
print(l.items())
# Would print [(5, '5'), (4, '4'), (3, '3'), (2, '2'), (1, '1')]
l[3] # Accessing an item would make it MRU
print(l.items())
# Would print [(3, '3'), (5, '5'), (4, '4'), (2, '2'), (1, '1')]
# Now 3 is in front
print(l.keys()) # Can get keys alone in MRU order
# Would print [3, 5, 4, 2, 1]
del l[4] # Delete an item
print(l.items())
# Would print [(3, '3'), (5, '5'), (2, '2'), (1, '1')]
print(l.get_size())
# Would print 5
l.set_size(3)
print(l.items())
# Would print [(3, '3'), (5, '5'), (2, '2')]
print(l.get_size())
# Would print 3
print(l.has_key(5))
# Would print True
print(2 in l)
# Would print True
print(l.get_stats())
# Would print (1, 0)
l.update({5: '0'}) # Update an item
print(l.items())
# Would print [(5, '0'), (3, '3'), (2, '2')]
l.clear()
print(l.items())
# Would print []
def evicted(key, value):
print("removing: %s, %s" % (key, value))
l = TTLRU(1, callback=evicted)
l[1] = '1'
l[2] = '2'
# callback would print removing: 1, 1
l[2] = '3'
# doesn't call the evicted callback
print(l.items())
# would print [(2, '3')]
del l[2]
# doesn't call the evicted callback
print(l.items())
# would print []
Notes and Technical Details
For more detailed information, please read the source code.
about ttl
- ttl = -1 means won't expire forever
- ttl is measured in nanoseconds. This is because Python's C-API
_PyTime_GetSystemClock
returns timestamp as nanoseconds, I don't want to do extra conversion.
When will ttl be checked?
- ttl is checked everytime when you try to access it, if expired, ttlru will remove the current item, and try to return a not expired item if possible:
- if you try to get a item like
result = l['a']
, if the item expired,None
will returned. - if you try to get the first or the last item using
peek_first_item()
orpeek_last_item()
, if the first or the last item expired, it will try the next item and return the first item that is not expired. if all items is expired, then returnNone
keys()
,values()
anditems()
method will go through all the linked list and remove the expired items, then returns a list with not expired items.
- if you try to get a item like
- ttl is not checkd when you access the statistics data.
- the
len(l)
will return count includes expired items. I think go through all the list to find not exist count is too expensive, maybe I can add another method to get the count of not expired items.
- the
What happened when insert an item?
- If the dict reached it's max size, then the last one will be removed. If there is an expired item but it is not the last one, then the expired item will still stay in the dict, only the last one will be removed. The reason is if I want to remove the expired one and keep the last one which is not expired, I have to use another data structure like a skip-table to keep the ttl order, which is not implemented in this version. For the other hand, the behavier above should be a TTL-Dict, not a TTL-LRU-Dict, Maybe I will write a TTL-Dict in the future.
Different behavier against normal dict
keys()
,values()
anditems()
returns a list, not a view object in Python3
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file ttlru-dict-1.0.1.tar.gz
.
File metadata
- Download URL: ttlru-dict-1.0.1.tar.gz
- Upload date:
- Size: 13.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.33.0 CPython/3.7.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 911a21a3ad3f68b8b6f9bb0b6f29d9d2100734f7d5d5fcd552ca42bcd4f44504 |
|
MD5 | 215e729a15b764c25bd1f1a89c8f369c |
|
BLAKE2b-256 | 7d9320001a23af1eecc4ef2b5b66207047b7370dca031afaf51bbe621ac38939 |