django 메모리 이상 검사 및 해결 방법 기록

원인
Django 는 Python 의 유명한 웹 프레임 워 크 로 서 많은 사람들 이 사용 하고 있 을 것 이 라 고 믿 습 니 다.자신의 작업 중 에 도 프로젝트 항목 이 사용 되 고 있 습 니 다.최근 며칠 동안 사용 한 결과 Django 프로그램 을 배치 한 서버 에 메모리 문제 가 발생 했 습 니 다.현상 은 한 동안 실행 한 후에 메모리 사용량 이 많 지 않 고 결국은 서버 의 메모리 가 소 진 되 고 Python 프로젝트 에 메모리 문제 가 발생 하 는 것 입 니 다.자신 이 이전에 한 번 처리 한 적 이 있 기 때문에 처음 해결 할 때 당황 하지 않 았 다.자신 이 전에 해결 방법 도 정리 했다.https://www.jb51.net/article/151604.htm
그러나 일 은 내 가 생각 하 는 것 처럼 그렇게 간단 하지 않 은 것 같다.스스로 이전의 방법 인 tracemalloc 라 이브 러 리 로 문 제 를 조사 하려 고 시도 했다.그러나 문 제 는 실제 프로젝트 에 100 여 개의 인터페이스 가 있 는데 어떻게 조사 합 니까?인터페이스 하나 로 테스트 검 사 를 하 는 것 은 아니 지만 시간 이 급 해서 또 늦 었 을 것 이다.지난번 에 스스로 해결 한 것 보다 지난번 프로젝트 가 간단 하고 상대 적 으로 포 지 셔 닝 문제 가 쉬 웠 기 때 문 입 니 다.그럼 이번 에는 어떻게 처리 하 시 겠 습 니까?
처리 과정
일반적으로 Python 프로젝트 는 메모리 문제 가 거의 발생 하지 않 습 니 다.보통 자신의 코드 에 문제 가 있어 서 발생 합 니 다.이번에 발생 한 문제 에 대해 자신의 조사 방향(웹 인터페이스 유형 에 대한 프로젝트):
  • 먼저 호출 이 비교적 빈번 한 인터페이스
  • 를 조사 했다.
  • 그 다음 에 데이터 집합 인터페이스(조회 가 복잡 하 다)
  • 상술 한 것 이 아직 밝 혀 지지 않 았 다 면 나머지 인 터 페 이 스 를 조사 하 라.
  • 이번 문제 조사 에서 자신 도 대체적으로 이 사고 에 따라 진행 되 었 다.호출 이 빈번 한 인 터 페 이 스 를 조사 할 때 메모리 의 이상 을 발견 하지 못 했 고 메모리 의 문 제 는 데이터 집합 과 관련 된 인터페이스 에 있다.
    사실 이런 인 터 페 이 스 는 초급 개발 에 문제 가 생기 기 쉬 운 부분 일 수 있다.먼저 이런 인터페이스 조회 의 데 이 터 는 다른 인터페이스 에 비해 비교적 복잡 할 것 이다.만약 에 인 코딩 기초 가 특별히 좋 지 않 으 면 이런 인터페이스 에 bug 가 나타 날 수 있다.
    이번 조사 에서 최종 적 으로 데 이 터 를 모 은 인터페이스 에서 문제 가 Django ORM 의 부적 절 한 사용 으로 인 한 것 으로 확인 되 었 다.자신 은 간단 한 코드 인 스 턴 스 를 통 해 설명 합 니 다.
    
    class Student(models.Model):
     name = models.CharField(max_length=20)
     name2 = models.CharField(max_length=20)
     name3 = models.CharField(max_length=20)
     name4 = models.CharField(max_length=20)
     name5 = models.CharField(max_length=20)
     name6 = models.CharField(max_length=20)
     name7 = models.CharField(max_length=20)
     name8 = models.CharField(max_length=20)
     name9 = models.CharField(max_length=20)
     name10 = models.CharField(max_length=20)
     name11 = models.CharField(max_length=20)
     name12 = models.CharField(max_length=20)
     name13 = models.CharField(max_length=20)
     name14 = models.CharField(max_length=20)
     name15 = models.CharField(max_length=20)
     age = models.IntegerField(default=0)
    정상 적 인 상황 에서 우리 의 표 필드 는 비교적 많 을 것 이다.여 기 는 여러 개의 name 을 통 해 시 뮬 레이 션 을 하고 문제 가 발생 한 코드 는 이 표 에 관 한 인터페이스 에서 나온다.
    
    def index(request):
     studets = Student.objects.filter(age__gt=20)
     if studets:
      pass
     return HttpResponse("test memory")
    메모리 문 제 를 쉽게 재현 하기 위해 저 는 스 크 립 트 를 통 해 Student 에 20000 개의 데 이 터 를 삽 입 했 습 니 다.물론 여기 데이터 가 많 을 수록 문제 가 뚜렷 합 니 다.
    테스트 스 크 립 트 를 통 해 이 인 터 페 이 스 를 요청 하고 메모리 상황 을 관찰 하면 메모리 가 순식간에 올 라 가 는 상황 을 발견 할 수 있 습 니 다.또한 데이터 가 많 을 수록 요청 이 많 을 수록 메모리 가 한동안 높 아 지지 않 고 점점 올 라 갈 수 있 습 니 다.문제 가 어디 에 있 습 니까?
    사실은 매우 간단 합 니 다.문 제 는 코드 에 있 는 if 판단 에 있 습 니 다.우 리 는 filter 조 회 를 통 해 Query Set 형식의 데 이 터 를 되 돌려 주 었 습 니 다.우리 가 걸 러 낸 데 이 터 는 매우 많은 경우 가 있 을 수 있 습 니 다.이때 우 리 는 if 를 통 해 직접 판단 합 니 다.이 지역 을 이해 해 야 전체 Query Set 을 메모리 에 불 러 와 메모리 사용량 이 너무 높 은 문제 가 발생 할 수 있 습 니 다.그리고 이때 이 인터페이스의 응답 속도 도 매우 느 려 집 니 다.이 Query Set 의 데이터 가 많 을 수록 메모리 사용량 이 뚜렷 합 니 다.
    Django 문서 에서 사실 설명 을 했 어 요.
    exists()¶
    Returns True if the QuerySet contains any results, and False if not. This tries to perform the query in the simplest and fastest way possible, but it does execute nearly the same query as a normal QuerySet query.
    exists() is useful for searches relating to both object membership in a QuerySet and to the existence of any objects in a QuerySet, particularly in the context of a large QuerySet.
    The most efficient method of finding whether a model with a unique field (e.g. primary_key) is a member of a QuerySet is:
    
    entry = Entry.objects.get(pk=123)
    if some_queryset.filter(pk=entry.pk).exists():
     print("Entry contained in queryset")
    Which will be faster than the following which requires evaluating and iterating through the entire queryset:
    
    if entry in some_queryset:
     print("Entry contained in QuerySet")
    And to find whether a queryset contains any items:
    
    if some_queryset.exists():
     print("There is at least one object in some_queryset")
    Which will be faster than:
    
    if some_queryset:
     print("There is at least one object in some_queryset")
    … but not by a large degree (hence needing a large queryset for efficiency gains).
    Additionally, if a some_queryset has not yet been evaluated, but you know that it will be at some point, then using some_queryset.exists() will do more overall work (one query for the existence check plus an extra one to later retrieve the results) than using bool(some_queryset), which retrieves the results and then checks if any were returned.
    그래서 저희 코드 에 대해 서 는 if 판단 부분 을 if not studtets.exists()로 바 꾸 면 문 제 를 해결 할 수 있 습 니 다.
    이것 은 아주 작은 지식 이지 만 잘못 사용 하면 매우 심각 한 메모리 문 제 를 일 으 킬 수 있다.
    총결산
    단원 테스트 를 제외 하고 빅 데이터 테스트 도 해 야 한다.이번 문 제 는 테스트 할 때 일정한 데이터 양 을 테스트 한 적 이 있다 면 일찍 발견 할 수 있 을 것 이다.
    문제.
    기초 라 이브 러 리 의 사용 에 대해 더욱 익숙해 져 야 한다.
    문 제 를 조사 하 는 방향 은 명확 해 야 한다.그렇지 않 으 면 손 쓸 길이 없 을 것 이다.
    연장 읽 기
  • https://docs.djangoproject.com/en/3.0/ref/models/querysets/
  • https://www.jb51.net/article/151604.htm
  • django 메모리 이상 검사 및 해결 방법 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 django 메모리 이상 검사 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기