From 1f7a4806ff41d270f94e0fa1f58ca09a70a087e3 Mon Sep 17 00:00:00 2001 From: Simon Mo Date: Thu, 3 Dec 2020 08:45:04 -0800 Subject: [PATCH] [Serve] Fix Flask Request self reference (#12560) * [Serve] Fix Flask Request self reference * Working flag * Fix --- python/ray/serve/http_util.py | 5 +++- python/ray/serve/tests/test_regression.py | 28 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/python/ray/serve/http_util.py b/python/ray/serve/http_util.py index 177a89f4b..da41c10eb 100644 --- a/python/ray/serve/http_util.py +++ b/python/ray/serve/http_util.py @@ -11,7 +11,10 @@ def build_flask_request(asgi_scope_dict, request_body): happen. """ wsgi_environ = build_wsgi_environ(asgi_scope_dict, request_body) - return flask.Request(wsgi_environ) + # We set populate_request=False to prevent self reference, which can lead + # to objects tracked by python garbage collector and memory growth. See + # https://github.com/ray-project/ray/issues/12395. + return flask.Request(wsgi_environ, populate_request=False) def build_wsgi_environ(scope, body): diff --git a/python/ray/serve/tests/test_regression.py b/python/ray/serve/tests/test_regression.py index 010478211..027b53a72 100644 --- a/python/ray/serve/tests/test_regression.py +++ b/python/ray/serve/tests/test_regression.py @@ -1,6 +1,9 @@ +import gc + import numpy as np import requests +import ray from ray import serve @@ -35,6 +38,31 @@ def test_np_in_composed_model(serve_instance): assert result.json() == 100.0 +def test_backend_worker_memory_growth(serve_instance): + # https://github.com/ray-project/ray/issues/12395 + client = serve_instance + + def gc_unreachable_objects(flask_request): + gc.set_debug(gc.DEBUG_SAVEALL) + gc.collect() + return len(gc.garbage) + + client.create_backend("model", gc_unreachable_objects) + client.create_endpoint("model", backend="model", route="/model") + + handle = client.get_handle("model") + + for _ in range(10): + result = requests.get("http://127.0.0.1:8000/model") + assert result.status_code == 200 + num_unreachable_objects = result.json() + assert num_unreachable_objects == 0 + + for _ in range(10): + num_unreachable_objects = ray.get(handle.remote()) + assert num_unreachable_objects == 0 + + if __name__ == "__main__": import sys import pytest