Low RPS when perfomance testings django website
I have a code like this that caches a page for 60 minutes:
import os
import time
from django.conf import settings
from django.core.cache import cache
from django.core.mail import send_mail
from django.contrib import messages
from django.http import FileResponse, Http404, HttpResponse
from django.shortcuts import render
from django.utils.translation import get_language, gettext as _
from apps.newProduct.models import Product, Variants, Category
from apps.vendor.models import UserWishList, Vendor
from apps.ordering.models import ShopCart
from apps.blog.models import Post
from apps.cart.cart import Cart
# Cache timeout for common data
CACHE_TIMEOUT_COMMON = 900 # 15 minutes
def cache_anonymous_page(timeout=CACHE_TIMEOUT_COMMON):
from functools import wraps
from django.utils.cache import _generate_cache_header_key
def decorator(view):
@wraps(view)
def wrapper(request, *args, **kw):
if request.user.is_authenticated:
return view(request, *args, **kw)
lang = get_language() # i18n
curr = request.session.get('currency', '')
country = request.session.get('country', '')
cache_key = f"{view.__module__}.{view.__name__}:{lang}:{curr}:{country}"
resp = cache.get(cache_key)
if resp is not None:
return HttpResponse(resp)
response = view(request, *args, **kw)
if response.status_code == 200:
cache.set(cache_key, response.content, timeout)
return response
return wrapper
return decorator
def get_cached_products(cache_key, queryset, timeout=CACHE_TIMEOUT_COMMON):
lang = get_language()
full_key = f"{cache_key}:{lang}"
data = cache.get(full_key)
if data is None:
data = list(queryset)
cache.set(full_key, data, timeout)
return data
def get_cached_product_variants(product_list, cache_key='product_variants', timeout=CACHE_TIMEOUT_COMMON):
lang = get_language()
full_key = f"{cache_key}:{lang}"
data = cache.get(full_key)
if data is None:
data = []
for product in product_list:
if product.is_variant:
data.extend(product.get_variant)
cache.set(full_key, data, timeout)
return data
def get_all_cached_data():
featured_products = get_cached_products(
'featured_products',
Product.objects.filter(status=True, visible=True, is_featured=True)
.exclude(image='')
.only('id','title','slug','image')[:8]
)
popular_products = get_cached_products(
'popular_products',
Product.objects.filter(status=True, visible=True)
.exclude(image='')
.order_by('-num_visits')
.only('id','title','slug','image')[:4]
)
recently_viewed_products = get_cached_products(
'recently_viewed_products',
Product.objects.filter(status=True, visible=True)
.exclude(image='')
.order_by('-last_visit')
.only('id','title','slug','image')[:5]
)
variants = get_cached_products(
'variants',
Variants.objects.filter(status=True)
.select_related('product')
.only('id','product','price','status')
)
product_list = get_cached_products(
'product_list',
Product.objects.filter(status=True, visible=True)
.prefetch_related('product_variant')
)
return featured_products, popular_products, recently_viewed_products, variants, product_list
def get_cart_info(user, request):
if user.is_anonymous:
return {}, 0, [], 0, []
cart = Cart(request)
wishlist = list(UserWishList.objects.filter(user=user).select_related('product'))
shopcart_qs = ShopCart.objects.filter(user=user).select_related('product','variant')
shopcart = list(shopcart_qs)
products_in_cart = [item.product.id for item in shopcart if item.product]
total = cart.get_cart_cost()
comparing = len(request.session.get('comparing', []))
compare_var = len(request.session.get('comparing_variants', []))
total_compare = comparing + compare_var
if len(cart) == 0:
shopcart = []
return {
'cart': cart,
'wishlist': wishlist,
'shopcart': shopcart,
'products_in_cart': products_in_cart,
}, total, wishlist, total_compare, shopcart
@cache_anonymous_page(3600)
def frontpage(request):
featured_products, popular_products, recently_viewed_products, variants, product_list = get_all_cached_data()
var = get_cached_product_variants(product_list)
cart_ctx, total, wishlist, total_compare, shopcart = get_cart_info(request.user, request)
context = {
'featured_products': featured_products,
'popular_products': popular_products,
'recently_viewed_products': recently_viewed_products,
'variants': variants,
'var': var,
**cart_ctx,
'subtotal': total,
'total_compare': total_compare,
}
return render(request, 'core/frontpage.html', context)
I installed django debug toolbar and it shows time ~40 ms for a cached frontpage. My server has 2 CPUs. When i try perfomance testing using locust I get around 3 RPS. I thought i would get around 2CPU*(1000/40) ~ 50 RPS.
I run my server using this command inside docker container:
gunicorn main.wsgi:application
-k gevent
--workers 6
--bind 0.0.0.0:8080
--worker-connections 1000
--timeout 120
Also i use psycopg2 with psycogreen wsgi.py starts with this:
from psycogreen.gevent import patch_psycopg
patch_psycopg()
What am i doing wrong? Why can't handle more RPS?