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?

Вернуться на верх