redis / hiredis-py

Python wrapper for hiredis
MIT License
494 stars 102 forks source link

Memory leak on hgetall with RESP3 and hiredis #175

Open HarukaMa opened 10 months ago

HarukaMa commented 10 months ago

X-posting from https://github.com/redis/redis-py/issues/3025.

Version: Redis 7.0.13, redis-py 5.0.1, hiredis 2.2.3

Platform: Python 3.11.6 on Debian sid

Description:

When using hiredis with RESP3, hgetall leaks memory. And it leaks hard - it seems all requested data will persistently live in the memory.

It's easy to reproduce:

from redis import Redis

r = Redis(protocol=3)
for _ in range(1000000):
    r.hgetall("any_hash_key")

hget and hvals are fine, and when using RESP2 it works as intended as well.

Stack from memray (most recent call last):

return await conn.retry.call_with_retry(
return await do()
return await self.parse_response(conn, command_name, **options)
response = await connection.read_response()
response = await self._parser.read_response(
response = self._reader.gets() 

All leaks happen on the last call. (Captured with program in production which uses async Redis, not from the example above)

lemurchik commented 8 months ago

Looks like RESP3 usage has memory leaks for all commands that have map replies. I had it during streams and TS usage.

InvisibleMan1306 commented 5 months ago

Is there any interest in fixing this? I can give it a try but I need to know where to start looking.