플러팅 AI/Flask Server

Paddle OCR 메모리 누수 (memory leak) 비교

Solo.dev 2024. 11. 19. 04:09

 

Paddle OCR 사용중 메모리 누수가 너무 심해서 메모리 추적을 한번 해봤는데요 

일단 서버에 지속적으로 이미지를 보내주는 python 코드를 간단하게 짜서 

1초 간격으로 이미지를 계속 보냈습니다.

총 이미지는 320장 보냈고 그 후 

mprof run --interval 0.5 python flask_server.py  명령어 통해서

메모리를 .dat 파일로 기록해줍니다

그후 메모리를 그래프화 하려면 아래 코드를 진행시켜 주면

mprof plot .\resources.dat

아래 사진처럼 메모리추적을 해주니 실제 어플리케이션 배포 시 

많은 요청이 오면 어떻게 대응하는지 한번 살펴볼게요 

 

1. 프로젝트 기본 코드 

  • 일단 기본으로 돌렸을때는 메모리가 아래 처럼 됩니다.
  • 처음 구간에 Paddleocr,yolov5 모델 로드 때문에 급증하는 구간이 있죠 이건 정상입니다.
  • 근데 다음 이미지 처리하면서 바로 또 급증을하죠? 메모리가 1000뚫어버립니다.
  • 그 다음 정상 동작이라면 메모리를 삭제시켜 줘야 하는데 삭제를 못 하고 있는 상황입니다
  • 그대로 시간 지나면 지날 수록 쭉 쭉 올라갑니다 오른쪽 아래에 내려가는 부분이 있는데 이건 잘모르겠습니다 
  • 아마 Paddle OCR 이 자체 메모리 관리하면서 내려간것으로 추정합니다

 

 

2.  비동기모드:  gevent 에서 threading 으로 교체 

  • 원래 사용하던 async_mode= gevent  대신 threading 으로 교체해봤습니다. 
  •  gevent vs threading
    멀티태스킹 방식 협력적 멀티태스킹 (Greenlet) 선점형 멀티태스킹 (OS 스레드)
    I/O 바운드 작업 매우 효율적 보통
    CPU 바운드 작업 비효율적 효율적
    메모리 사용량 상대적으로 적음 상대적으로 많음
    호환성 표준 라이브러리를 패치해야 함 표준 Python 스레드 사용
    복잡성 더 많은 설정과 코드 수정 필요 더 직관적이고 설정이 간단
  • 제가 CPU를 사용하기 때문에 혹시 몰라서 threading 사용해봤는데 결과는 아래 그래프입니다.

 

  • 기대했던 제가 바보죠 비슷한 양상을 보입니다 여기도 처음에 모델로딩 하느라 쭉 뜁니다.
  • 그리고 점차 이미지를 계속 추론 하면서 올라가다가 1500에서 2500으로 확 뛰죠 ?
  • 확인해보니 이런 경우는 OCR이 글자가 아닌 이상한 도형? 같은거 있는 이미지일떄 확 뛰더라구요
  • 그다음은 계속 유지 되는 듯 합니다만 사실 메모리가 3000에서 유지되는 게 이상한거 아닌가요 ?
  • 제가 아래 코드 통해서 Upload 앤드포인트 요청 끝날 때 마다 가바지 컬렉션을 수행했거든요  
  • @app.teardown_request
    def teardown_request_func(exception=None):
        try:
                 
            gc.collect()  # 강제로 가비지 컬렉션 수행
            logger.info("요청 완료 후 OCR 모델 메모리 해제")
        except Exception as e:
            logger.error(f"teardown_request에서 오류 발생: {e}")

 

3.  cleanup_resources() 함수 만들어서  Upload 앤드포인트 중간에 적용 

  • 일단 비동기 모드 gevent로 다시 되돌려줍니다 .
  • 그다음 리소스 정리하는 cleanup_resources 함수를 만들고
    def cleanup_resources(self):
        """추론 후 사용된 리소스 정리"""
        try:
            gc.collect()
            logger.info("추론 후 메모리 정리 완료")
        except Exception as e:
            logger.error(f"리소스 정리 중 오류 발생: {e}")
            logger.error(traceback.format_exc())

 

  • 이걸 이미지가 들어오면 전체 동작을 수행하는 Upload 앤드포인트 중간에 넣어줄겁니다 .
  • 원래는 모든 동작이 끝나면 gc.collect() 를 수행했었는데 
  • cleanup_resources를 이미지 처리가 다 끝난 후 호출해줍니다 .
  • 그렇게 하고 돌린 메모리 로그가 아래 그래프입니다.

 

 


 

4. 정리 

  • Paddle OCR 메모리 누수 확실함
  • 혹시 몰라 가장 최근에 나온 Paddlepaddle 3.0베타버전으로 실험도 해봤지만 여전히 메모리 누수 
  • Paddle OCR 공식 문서에 있는 메모리 관리 방법도 따라서 해봤지만 여전히 메모리 누수 
  • 메모리가 정리가 안됨 Python 문제는 아닐거고 아마 Paddle OCR 문제가 확실한데 방법을 모르겠음
  • 정 안되면 Tesseract로 대체 예정 하지만 Tesseract는 정확도가 떨어짐 

 

 

틀린 점이나 수정할 점 있다면 항상 환영입니다. 부족한 저에게 지식을 나눌 기회를 주십쇼 감사합니다.