diff options
author | Andy Doan <andy.doan@linaro.org> | 2016-06-17 14:41:40 -0500 |
---|---|---|
committer | Andy Doan <andy.doan@linaro.org> | 2016-07-05 19:47:05 +0000 |
commit | 3d654185bc11a834c7b0bb1a12cc76ec44f313ea (patch) | |
tree | 58b5de75e7ffbdcd6a7c1cc0bbcf1e1182e22fb7 | |
parent | f38c5548c0f7fa4ff4bf172dfbaf5b83090de889 (diff) |
Add caching logic to most expensive APIs
We've recently encountered a pretty major degradation in s3 API
performance. I originally skipped caching logic because things were
"good enough" and I was scared to mess up cache logic. However, page
loads are now routinely taking over 4s. My stats for the last 2 hours
were:
Average: 1.876110 (0.649776 %stddev)
So the average isn't great and the standard deviation is huge which
means we get really common *large* outliers. This patch is built on 2
simple ideas:
#1 - caching is safe for releases.l.o. This is safe because we publish
here once a month and then things are "static".
#2 - find_artifact and dir_list are the most expensive calls
for #1, we'll have to patch releases_us_secrets.py with:
CACHES = {
'default': {
'BACKEND':
django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/tmp/releases-django-cache',
'TIMEOUT': 5 * 60, # 5 minute cache
}
}
Change-Id: I3effd75a5946d6f8a95dc6a626436a02987f4617
Reviewed-on: https://review.linaro.org/12768
Reviewed-by: Paul Sokolovsky <paul.sokolovsky@linaro.org>
Reviewed-by: Ben Copeland <ben.copeland@linaro.org>
-rw-r--r-- | license_protected_downloads/common.py | 11 | ||||
-rw-r--r-- | license_protected_downloads/tests/__init__.py | 1 | ||||
-rw-r--r-- | license_protected_downloads/views.py | 5 | ||||
-rw-r--r-- | settings.py | 7 |
4 files changed, 21 insertions, 3 deletions
diff --git a/license_protected_downloads/common.py b/license_protected_downloads/common.py index e4755fd..0fe948a 100644 --- a/license_protected_downloads/common.py +++ b/license_protected_downloads/common.py @@ -4,6 +4,7 @@ import os import boto from django.conf import settings +from django.core.cache import cache from django.http import Http404 from license_protected_downloads import models @@ -31,6 +32,16 @@ def safe_path_join(base_path, *paths): return target_path +def cached_call(key, func, *args, **kwargs): + key = func.__name__ + key + v = cache.get(key) + if v: + return v + v = func(*args, **kwargs) + cache.set(key, v) + return v + + def _handle_wildcard(request, fullpath): path, name = os.path.split(fullpath) diff --git a/license_protected_downloads/tests/__init__.py b/license_protected_downloads/tests/__init__.py index 307b75f..805675e 100644 --- a/license_protected_downloads/tests/__init__.py +++ b/license_protected_downloads/tests/__init__.py @@ -1,4 +1,3 @@ - from license_protected_downloads.tests.test_buildinfo import * from license_protected_downloads.tests.test_api_v1 import * from license_protected_downloads.tests.test_api_v2 import * diff --git a/license_protected_downloads/views.py b/license_protected_downloads/views.py index 9ee198c..a1c670b 100644 --- a/license_protected_downloads/views.py +++ b/license_protected_downloads/views.py @@ -25,6 +25,7 @@ from group_auth_common import GroupAuthError import xml.dom.minidom as dom from license_protected_downloads.common import ( + cached_call, dir_list, find_artifact, ) @@ -219,7 +220,7 @@ def _check_file_permission(request, artifact, internal): def file_server_get(request, path): - artifact = find_artifact(request, path) + artifact = cached_call(path, find_artifact, request, path) internal = get_client_ip(request) in config.INTERNAL_HOSTS if not internal: @@ -233,7 +234,7 @@ def file_server_get(request, path): return resp if artifact.isdir(): - return _handle_dir_list(request, artifact) + return cached_call(path, _handle_dir_list, request, artifact) # prevent download of files like BUILD-INFO.txt if artifact.hidden(): diff --git a/settings.py b/settings.py index 02c5244..ac74584 100644 --- a/settings.py +++ b/settings.py @@ -185,6 +185,13 @@ LOGGING = { } } +# disable caches by default for testing (enabled in production) +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + } +} + import django if django.VERSION < (1, 6): # old django needs a hack to not send emails for ALLOWED_HOSTS violations |