kakao / khaiii

Kakao Hangul Analyzer III
Apache License 2.0
1.41k stars 284 forks source link

flask restful server 대용량 KhaiiiApi 요청 시 메모리 누수 문의 #61

Closed woososim closed 5 years ago

woososim commented 5 years ago

flask 프레임워크를 이용하여 웹 서비스형태로 카이를 사용하고자 하였습니다. 아래 형태로 구성하여 사용 중인데 지속적으로 웹 요청 발생 시 메모리가 감소 없이 증가만 되고 있습니다. 결국에는 메모리 오버플로우를 발생시키는데 혹시 아래코드에 문제가 있을까요?

from flask import Flask, jsonify from flask import Response from collections import OrderedDict from flask_cors import CORS from flask_json import FlaskJSON, JsonError, json_response, as_json from flask_restful import Resource, Api from flask_restful import reqparse from khaiii import KhaiiiApi import logging import gc

app = Flask(name) api = Api(app) app.debug = False app.logger.disabled = True log = logging.getLogger('werkzeug') log.disabled = True

cors = CORS(app, resources={r"/analyze/": {"origin": ""}})

class Khaiii_Analyze(Resource): def get(self): try: json = FlaskJSON(app) json.init_app(app)

        parser = reqparse.RequestParser()
        parser.add_argument('keyword', type=str)
        args = parser.parse_args()

        khaiii_api = KhaiiiApi()
        khaiii_api.open()

        arr_word = khaiii_api.analyze(args['keyword'])
        result_word = []

        for idx in range(len(arr_word)):
             s = str(arr_word[idx])
             wordList = {'word': s}
             result_word.append(wordList)
             del(wordList)
             del(s)
             wordList = None
             s = None

        del(arr_word)
        del(parser)
        del(args)
        json_iter = iter(result_word)
        del(result_word)
        khaiii_api.close()
        del(khaiii_api)
        arr_word = None
        result_word = None
        khaiii_api = None

        json_str = json_response(items=json_iter, headers_={'content_type': 'application/json; charset=utf-8'})
        del(json)
        json = None
        gc.collect()

        return json_str

    except Exception as e:
        return {'Error': str(e)}

api.add_resource(Khaiii_Analyze, '/analyze')

if name == 'main':

krikit commented 5 years ago

우선 매 request 마다 KhaiiiApi 객체를 생성하고 analyze() 메소드를 호출한 후 객체를 제거하고 있는데요. 이 부분부터 손을 보시는 것이 어떨까 합니다. 즉, 웹서버가 실행될 때 한번만 KhaiiiApi 객체를 생성하시고, request 시에는 analyze() 메소드만 호출하여 처리하도록 하는 것이 좋아 보입니다.

이런 구조의 변화는 속도의 개선에도 효과가 있지만, 말씀하시는 메모리 증가를 방지하는 효과도 있지 않을까 생각합니다. gc 기반의 언어는 객체가 정확히 원하는 때에 소멸된다고 보장하기 힘들기 때문에 불필요하게 객체를 많이 생성하지 않는 것이 좋을 것이라 생각해서 입니다.

그리고 큰 건 아니지만 객체 생성 시 내부적으로 open() 메소드를 호출하게 되어 있으니, open() 메소드를 명시적으로 호출하면 기존에 열었던 리소스를 닫고 다시 열게 되므로 불필요한 시간을 소비하게 된다는 점도 참고하시기 바랍니다.

woososim commented 5 years ago

답변 감사합니다.

많은 도움이 되었습니다.