Skip to main content

A smarter local memory cache backend for Django

Project description

django-lrucache-backend

Latest PyPI version Latest Travis CI build status

A smarter local memory cache backend for Django.

Cache Performance

Set Performance. Delete performance.

About

lrucache_backend is an in-memory cache that improves upon the existing LocMemCache that Django provides.

Comes with cache timeouts and a smart eviction strategy that prefers to keep keys that are used often and evict keys that are not.

Originally developed to avoid poorly reimplementing local object stores for service layer objects. For example:

def get_data_before(self):
    if not hasattr(self, '__data'):
        self.__data = self.expensive_query()
    return self.__data

def get_data_after(self):
    lcache = caches['local']
    data = lcache.get('our_data')
    if not data:
        data = self.expensive_query()
        lcache.set('our_data', data, timeout=600)
    return data

The benefits (despite the longer method) include timeouts, sharing data between requests, and avoiding network requests. This is especially useful when there are hundreds or thousands of property accesses that would hit the cache where network overhead would be prohibitive. The Fat model pattern can greatly benefit from tiered caching.

Good for?

An in memory cache is good for small data that changes rarely. It’s effectively a global dictionary shared between requests in the same process. Small lookup tables and database backed settings are good candidates.

A small number of keys should be used to avoid engaging the culling strategy of the cache. Performance goes down fast as soon as the maximum number of keys are reached, and keys start to evict.

This should not be used as your primary cache, but it makes for an excellent secondary cache when you want to avoid the overhead of a network call.

Use for:

  • Small lookup tables

  • Settings

  • Backing store for your service objects

  • Remembering values for the duration of a request or celery task

  • Small global template fragments like sidebars or footers

  • Secondary cache

Bad for?

An in memory cache is terrible for data that changes often. Because the cache is process local, it’s extremely difficult to coordinate cache invalidation from external processes. For that reason, this library does nothing to support cache invalidation.

The cache shares memory with the application, so it’s extremely important to avoid storing a lot of keys, or any large values.

Do not use for:

  • Instance attributes/properties

  • Full templates

  • Tables with a large number of rows

  • Large values

  • Large lists

  • Primary cache

Differences from LocMemCache

  • Avoids pickling

  • Avoids key name validation

  • Uses an LRU eviction algorithm rather than a random percentage culling strategy

Installation

pip install django-lrucache-backend

Requirements

lru-dict is implemented in C and is unlikely to work with non-CPython implementations. There are compatible pure python libraries. If you need this ability, please open an Issue!

Usage

Configure your CACHES Django setting appropriately:

CACHES = {
    'local': {
        'BACKEND': 'lrucache_backend.LRUObjectCache',
        'TIMEOUT': 600,
        'OPTIONS': {
            'MAX_ENTRIES': 100
        },
        'NAME': 'optional-name'
    }
}

And then use the cache as you would any other:

>>> from django.core.cache import caches

>>> local = caches['local']
>>> local.set('key', 123)
>>> local.get('key')
... 123

If you’re going to use this cache backend, then it’s highly recommended to use it as a non-default cache. That is, do not configure this cache under the default name.

Local memory caches compete for memory with your application so it’s in your best interests to use it as sparingly and deliberately as possible.

Compatibility

Django 1.8 - Django master. All Python versions supported by compatible Django versions.

Licence

MIT

Authors

django-lrucache-backend was written by Josh Smeaton.

History

0.2.0 (2017-07-16)

  • Don’t validate the key
    • delete P90: 20% improvement

    • set P90: 17% improvement

    • get P90: 10% improvement

Benchmarks

python benchmark.py -r 500 --complex

========= ========= ========= ========= ========= ========= ========= =========
Timings for lrumem-objects-500-0.2.0
-------------------------------------------------------------------------------
   Action     Count      Miss    Median       P90       P99       Max     Total
========= ========= ========= ========= ========= ========= ========= =========
      get    712827     99120  33.855us  59.843us  81.062us  37.626ms  28.899s
      set     71262         0  35.048us  37.909us  73.195us   5.847ms   2.719s
   delete      7903         0  32.902us  35.048us  63.896us   1.114ms 272.343ms
    Total    791992                                                    31.891s
========= ========= ========= ========= ========= ========= ========= =========

0.1.0 (2017-07-13)

  • Project comes online

Benchmarks

python benchmark.py -r 500 --complex

========= ========= ========= ========= ========= ========= ========= =========
Timings for locmem-objects-500
-------------------------------------------------------------------------------
   Action     Count      Miss    Median       P90       P99       Max     Total
========= ========= ========= ========= ========= ========= ========= =========
      get    712827     99120  51.022us  67.949us 127.077us  13.318ms  41.607s
      set     71262         0  59.128us  66.042us 154.018us   6.350ms   4.693s
   delete      7903         0  42.915us  46.015us  81.062us   3.040ms 361.492ms
    Total    791992                                                    46.661s
========= ========= ========= ========= ========= ========= ========= =========


========= ========= ========= ========= ========= ========= ========= =========
Timings for lrumem-objects-500
-------------------------------------------------------------------------------
   Action     Count      Miss    Median       P90       P99       Max     Total
========= ========= ========= ========= ========= ========= ========= =========
      get    712827     99120  41.008us  66.996us 102.043us  29.211ms  34.952s
      set     71262         0  42.915us  46.015us  84.162us  16.403ms   3.313s
   delete      7903         0  40.054us  43.869us  80.824us   1.426ms 340.591ms
    Total    791992                                                    38.605s
========= ========= ========= ========= ========= ========= ========= =========

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-lrucache-backend-0.2.1.tar.gz (13.0 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page