django漂亮的模板_使用DTrace和cProfile分析Django性能

d0fe1dc10b3f9c76383eba89c74e3b4a.png

Django是一个非常棒的框架,相当重要的原因是它包含了快速创建web应用程序所需的一切。但是开发者不应该是唯一的受益者。这个应用程序对用户来说也应该更快。

官方文档中有一章是关于性能和优化的,其中提供了很好的建议。在本文中,我将在此基础上展示我过去用来减少页面加载时间的工具和方法。

测量 & 收集数据

性能基准测试和概要分析对于任何优化工作都是必不可少的。盲目地应用优化可能会增加代码库的复杂性,甚至可能使情况变得更糟。

我们需要性能数据来了解应该关注哪些部分,并验证任何更改是否达到了预期的效果.

django-debug-toolbar

django-debug-toolbar很容易使用,并且有一个很好的界面。它可以显示每个SQL查询花费了多少时间,并有一个快速按钮可以获得该查询的EXPLAIN输出和其他一些有趣的细节。template-profiler是一个额外的面板,用于添加有关模板呈现过程的分析数据。

不过,django-debug-toolbar也有一些缺点。由于它集成到站点中的方式,所以只有在DEBUG = True的开发环境中使用它是有意义的。它本身也会带来巨大的性能损失。

DTrace

DTrace就没有这些限制。它可以用于生产服务,并提供比项目的python部分更多的细节。您可以深入了解数据库、python解释器、web服务器和操作系统,以获得每个地方时间花费的完整信息。

这将发生在CLI中,而不是漂亮的浏览器UI中。DTrace脚本是用类AWK语法编写的。在dtracetools包中还有一些有用的脚本。当您使用Joyent pkgsrc repos时,您可以使用一下代码来安装它:

55c8f8ae2b25e64a1238d9c06f12786f.png

这个包中有用的脚本之一是dtrace-mysql_query_monitor.d,它将显示所有的MySQL查询:

f52e4830b90ef7ff9dabbf6e6ce7af69.png

您也可以对PostgreSQL做同样的事情:

5bbd5227ace55b7d82b8e0f65f5b6f97.png

输出将会像这样:

b4002b62146f0f0c2fbca2cf1361b198.png

在dtracetools包中有一些非常有用的dtrace-py_*脚本,可以帮助你深入了解python过程本身。例如dtrace-py_cputime.d将显示一个函数的调用次数以及包含和不包含CPU的时间:

54105f66f29d145d9a7f0c00fee2a0b0.png

在本例中,我们看到在正则表达式相关的东西上花费了一些时间,可能与URL路由有关。

cProfile

标准的python库附带了cProfile,它将收集函数调用的精确时间。我们可以将它与django test client一起使用来进行自动化性能测试。

尽可能多地自动化性能数据收集步骤有助于快速迭代。在最近的一个项目中,我创建了一个专用的manage.py命令来分析最重要的URL。它看起来像这样:

8babb9af1e90799fe30ca11f380ad8ba.png

我们不但可以打印统计数据,还可以使用pr.dump_stats(fn)将统计数据保存到磁盘。这允许我们使用flameprof进行进一步处理来创建火焰图。

419dee9223fa8a401e1120079760d86a.png

20a1398b1e346aaa733f0f0adf54e1f5.png

%timeit

另一个来自标准库的方便实用程序是timeit。你会经常发现这样的例子:

d7635f906e9b6921cb1645b76f59cac6.png

这在对小型语句进行实验是很有用。

为了更进一步,我建议您安装IPython,它会将Django manage.py shell 转换成一个非常强大的开发环境。

除了tab-补全和其他上千个功能外,你还会拥有%timeit魔法。

faacb3d4f06bf0815d992e1bd47516d2.png

优化

一旦你知道你的项目中哪些部分是最慢的,你就可以开始改进这些部分。通常大部分时间是花在数据库查询上,然后是模板呈现。

虽然每个项目可能需要不同的优化,但也有一些常见的模式。

预加载相关的对象

当您在模板中显示一个对象列表并访问一个相关对象的某个字段时,将触发一个额外的数据库查询。这些耗时很容易地叠加起来,并导致针对一个请求的大量查询。

当您知道您将需要哪些相关字段时,您就可以告诉Django以更有效的方式去获得这些字段。两个重要的方法是select_related()和prefetch_related()。

select_related()通过使用一个SQL JOIN prefetch_related()为每个查找创建一个查询。它们易于使用,几乎不需要对现有代码进行任何修改,并且可以带来巨大的改进。

索引

另一个容易应用的性能调整是确保您有正确的数据库索引。无论您何时使用一个字段进行filter,在某些情况下是进行order_by,您都应该考虑是否需要索引。创建索引与向模型字段添加db_index = True一样简单,然后创建并运行结果迁移。确保使用SQL EXPLAIN去验证改进。

缓存

缓存是一个很大的主题,有很多方法可以通过缓存来提高django的性能。根据环境和性能特征,使用缓存的位置、持续时间和层将不同。

django cache 框架是在各个层上利用Memcached的一种简单方法。@cached_property装饰器通常对胖模型方法很有帮助。

>>> 今日签到口令:8wgf <<<

预计算

有些计算对于一个HTTP请求的时间预算来说太长了。在这些情况下,我发现在后台进程中预先计算所需的数据是很有用的。这可以通过像Celery这样的任务队列来完成,也可以通过一个manage.py命令来降低复杂性,该命令可以作为一个服务或作为一个定时任务长期运行。

Django之外

除了这些常见的情况外,还有许多进一步优化web项目的方法。通过反规范化更改数据库模式可能会改进一些查询。其他技术将在很大程度上取决于项目的环境。

通常也有很多机会去优化堆栈和下面的东西。从浏览器中测量性能数据,在Django中花费的时间只会越来越少。有了这些新数据,你就可以开始处理DOM渲染、CSS和JS,减少图像请求大小或更好的网络路由。

查看更低级别的改进也能带来巨大的好处。即使是低级别的小改进也会导致性能的提高,这仅仅是因为这些部分运行得太频繁了。

最近的一个例子是,通过改变python解释器的编译方式,每个请求获得了约120ms的提升。我测试的cpython版本中已经启用了retpoline缓解。这是一个孤立的内部服务,而威胁模型是不需要这个服务的。因此,仅通过不使用-mindirect-branch=thunk-inline -mfunction-return=thunk-inline -mindirect-branch-register进行编译就可以极大地提高性能。

如果您的web项目需要进行一些性能优化,请随时联系我们!

英文原文:https://wiedi.frubar.net/blog/2019/11/18/django-performance/ 
译者:Nothing
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django_celery_beat是一个django应用程序,它允许您使用celery定期运行周期性任务。这些周期性任务可以是一次性的或循环的,你可以设置它们在指定的时间间隔内自动运行,也可以设置它们在特定的时间运行。 要使用django_celery_beat,请按照以下步骤操作: 1. 安装django_celery_beat: ``` pip install django_celery_beat ``` 2. 在settings.py中添加以下代码: ``` INSTALLED_APPS = [ # ... 'django_celery_beat', ] CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler' ``` 3. 在项目的urls.py文件中添加以下代码: ``` from django.urls import path from django_celery_beat.views import ( PeriodicTaskListView, PeriodicTaskCreateView, PeriodicTaskUpdateView, PeriodicTaskDeleteView, PeriodicTaskDetailView, ) urlpatterns = [ # ... path('celery/periodic-tasks/', PeriodicTaskListView.as_view(), name='periodic_task_list'), path('celery/periodic-task/add/', PeriodicTaskCreateView.as_view(), name='periodic_task_create'), path('celery/periodic-task/<int:pk>/', PeriodicTaskDetailView.as_view(), name='periodic_task_detail'), path('celery/periodic-task/<int:pk>/update/', PeriodicTaskUpdateView.as_view(), name='periodic_task_update'), path('celery/periodic-task/<int:pk>/delete/', PeriodicTaskDeleteView.as_view(), name='periodic_task_delete'), ] ``` 4. 在celery.py文件中添加以下代码: ``` from celery import Celery from django.conf import settings app = Celery('my_project') app.config_from_object('django.conf:settings', namespace='CELERY') app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) ``` 5. 在tasks.py文件中创建您的任务,例如: ``` from celery import shared_task @shared_task def my_task(): # Do something here ``` 6. 创建周期性任务,您可以使用Django admin或创建它们的视图。 现在,您已经可以在django使用celery定期运行周期性任务了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值