环境说明
- 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
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
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
=============================================================
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
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```