django开发的性能优化

在使用django在web项目开发中避免不了会进行性能优化,最近特意总结了一些我用到过的性能优化方法。都是实际开发过程中非常有用的技巧,希望能够对大家有所帮助。

性能分析工具

cprofile

from cProfile import Profile
import pstats

prof = Profile()
prof.enable()
# 运行函数
run_func()
prof.create_stats()

p = pstats.Stats(prof)
p.print_callees()

运行程序,可以看到每行代码执行所花费的时间
在这里插入图片描述

line_profiler

在函数名上添加@profile装饰器,然后使用

kernprof -l -v loopdemo.py

django-debug-toolbar

Django Debug Toolbar是Django开发中必备利器,可以帮助开发者快速了解项目的整体信息以及每个页面包括sql信息,http相关信息.

pip install django-debug-toolbar
  1. 打开项目文件夹settings.py 文件, 把"debug_toolbar"加到INSTALLED_APP里去。

  2. 打开项目文件夹里的urls.py, 把debug_toolbar的urls加进去。

from django.conf import settings
from django.conf.urls import include, url  
from django.urls import include, path  

if settings.DEBUG:
    import debug_toolbar
    urlpatterns = [
        path('__debug__/', include(debug_toolbar.urls)),

    ] + urlpatterns
  1. 在settings.py里添加中间件
MIDDLEWARE = [
    # ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    # ...
]
  1. 在settings.py设置本地IP, debug_toolbar只能在localhost本地测试环境下运行。
INTERNAL_IPS = [
    # ...
    '127.0.0.1',
    # ...
]

代码优化

# 使用values和values_list
Author.objects.values("name")
Author.objects.values_lsit('name')
# 使用 defer() 和 only() 来避免加载不需要的数据列
Author.objects.only("name")
Author.objects.defer("id", "age", "author_detail")

# objs.count()来替代len(objs),book.author_id代替book.author.id

# 尽量使用单语句查询,多使用annotate和aggregate聚合函数查询。以及filter=Q(field=value)的子查询条件。
Author.objects.values('age').annotate(male_sum=Sum('num', filter=Q(sex='male')))

# 使用select_related和prefetch_related
# select_related对正向查询和一对多的外键查询结果进行缓存
Book.objects.select_related('foreign').all()
# prefetch_related对反向查询和多对多的查询结果进行缓存
Author.objects.prefetch_related('book_set').all()

# 批量插入
Author.objects.bulk_create([Entry(name='a'),Entry(name='b'),])

# 查询集的惰性缓存
objs.iterator() 和 objs.exists()方法来防止生成cache

多任务

线程池

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor

def run(num):
    time.sleep(num)
    return num

def main():
	# 开启线程池
    with ThreadPoolExecutor(max_workers=5) as t:
        obj_list = []
        for numin range(1, 5):
            obj = t.submit(spider, num)
            obj_list.append(obj)
		for future in as_completed(obj_list):
			# 获取线程执行结果
			data = future.result()

进程池
ProcessPoolExecutor 使用同线程池,只不过进程池的使用依赖于__main__主程序入口

协程

import asyncio
import requests
import time

start = time.time()

async def get(url):
    return requests.get(url)
    
async def request():
    url = 'https://www.baidu.com/'
    # await后面要跟 coroutine 对象
    response = await get(url)

def callback(task):
    print('Status:', task.result())
    
# 得到一个croutine对象
coroutine = request()
# 创建一个task任务
task = asyncio.ensure_future(coroutine)
# 将task作为参数传递至回调函数中
task.add_done_callback(callback)

# 创建5个协程任务
tasks = [asyncio.ensure_future(request()) for _ in range(5)]
# 注册循环事件
loop = asyncio.get_event_loop()
# 将协程添加到循环事件中并执行
loop.run_until_complete(asyncio.wait(tasks))

# 不使用回调函数被我们依然可以使用task.result()来获取结果
for task in tasks:
	print(task.result())

针对不同的业务场景,我们需要分析影响性能的代码瓶颈在哪里,从而有针对性的做出相应的解决。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值