django drf 内存泄漏处理

环境说明

  • python 3.10
  • Django 5.0
  • windows 10
  • django-rest-framework 0.1.0
  • postgres 16

安装pip库

pip install memory_profiler 	# 第三方内存分析库
pip install matplotlib 			# 主要用于图形界面

开始进行分析

导入库

from memory_profiler import profile

装饰器

class Table(APIView):
    """返回表格数据"""
    renderer_classes = [CustomRenderer]	# 返回渲染,可以添加用户验证等

    @profile		# get请求这一块添加内存分析库的装饰器
    def get(self, request):
    	Response(status=200,data={"msg":"测试!"})
    	

装饰器带参数写法

@profile(precision=4,stream=open('memory_profiler.log','w+')) 

运行Django

mprof run nvenv/Scripts/python.exe manage.py runserver 0.0.0.0:8000 # 建议这种方式运行,否则报错没安装Django等库
# 不推荐的允许方式
mprof run python manage.py runserver 0.0.0.0:8000

发送请求获取数据后控制台可以看的内存分析的数据

(nvenv) PS D:\PycharmProjects\budget-disclosure> mprof run nvenv/Scripts/python.exe manage.py runserver 0.0.0.0:8000
mprof: Sampling memory every 0.1s
running new process
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
March 19, 2024 - 17:46:31
Django version 5.0, using settings 'BudgetDisclosure.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CTRL-BREAK.

Filename: D:\PycharmProjects\budget-disclosure\Budget\views.py

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
   413    119.0 MiB    119.0 MiB           1       @profile
   414                                             def get(self, request):
   415    119.0 MiB      0.0 MiB           1           institutions_code = request.query_params.get('institutions_code', None)
   416    119.0 MiB      0.0 MiB           1           district_code = request.query_params.get('district_code', None)        
   417    119.0 MiB      0.0 MiB           1           if institutions_code and district_code:
   418    119.0 MiB      0.0 MiB           1               state = 0
   419                                                     # 从Redis中获取数据
   420    119.0 MiB      0.0 MiB           1               value = cache.get(str(district_code) + str(institutions_code))
   421    119.0 MiB      0.0 MiB           1               if not value:
   422    119.0 MiB      0.0 MiB           1                   try:
   423    119.1 MiB      0.1 MiB           2                       value = BudgetLogs.objects.get(
   424    119.0 MiB      0.0 MiB           1                           institutions_code=institutions_code, district_code=district_code)
   425    119.1 MiB      0.0 MiB           1                       state = value.progress
   426    119.2 MiB      0.0 MiB           3                       value = BudgetLogsSerializer(
   427    119.2 MiB      0.1 MiB           2                           value, many=False).data['data']
   428
   429                                                         except Exception as e:
   430                                                             value = []
   431                                                     else:
   432                                                         state = 1
   433    119.2 MiB      0.0 MiB           1               fun = GetTable(institutions_code, district_code, value, state)
   434                                                     # 创建线程对象,传入参数
   435    119.2 MiB      0.0 MiB           1               res = {'redis': value}
   436    123.7 MiB      4.5 MiB           1               fun.get_table_data(res)
   437    123.7 MiB      0.0 MiB           1               try:
   438    123.7 MiB      0.0 MiB           1                   return Response(status=200, data=res)
   439                                                     except Exception as e:
   440                                                         print(e)
   441                                                         return Response(data=str(e), status=404)
   442                                                 else:
   443                                                     return Response(status=404, data={'message': "institutions_code or district_code is none!"})


[19/Mar/2024 17:46:46] "GET /api/table/?institutions_code=001002&district_code=653101 HTTP/1.1" 200 75713

查看内存分析图

  • 新建终端中运行命令
mprof plot
  • 图片
    在这里插入图片描述

加深处理解决方法

class(类)的子方法(def)上面可以添加装饰器,可以分析内存情况(class类的上面不能使用内存分析装饰器)

处理内存分析的集中方法

删除全局变量

del distract_data
del distract_data

清理模型的缓存

from Budget.models import Model
Model._fetch_all()

如需要清理Redis缓存

from django.core.cache import cache
cache.clear()

避免内存,如下简单案例

一下会存在内存泄漏

  • 在这个例子中,node1 和 node2 形成了循环引用,即使在代码中手动将它们设置为None,由于它们相互引用,垃圾回收器也无法释放它们占用的内存空间。
class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# 创建循环引用
node1 = Node(1)
node2 = Node(2)
node1.next = node2
node2.next = node1

# 释放引用
node1 = None
node2 = None

- 为了解决这个问题,可以使用弱引用(weak reference)来打破循环引用,或者重新设计数据结构以避免循环引用的产生。
```python
- 解决方法
import weakref

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None

# 使用弱引用
node1 = Node(1)
node2 = Node(2)
node1.next = weakref.ref(node2)
node2.next = weakref.ref(node1)

# 释放引用
node1 = None
node2 = None```
  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海哥0998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值