-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix excessive CPU usage due to polling with no sleep #150
Fix excessive CPU usage due to polling with no sleep #150
Conversation
Hi! |
Line 1061 in f8fc065
Here for example |
Maybe it's because I didn't get my coffee yet, but I don't see any loop that could consume CPU. Could you point me to where that happens exactly? |
My apologies – this is an issue I solved a while back for redis-py and forgot what it was about. This issue only seems to appear when the user runs get_message() repeatedly in order to filter/receive messages in a loop. The issue is that get_message() without any parameters is supposed to be blocking, but it is not, since the default parameter is 0.0 and not None (even though it seems like None was the intention, since it is compared to inside the function). This solved the redis-py issue redis/redis-py#3208, but since redis-py doesn't get much activity (and since I have switched to valkey), I thought it would be easier to fix it here. For example: def receive_sync(channel: str = CHANNEL, connection: redis.Redis = REDIS_SYNC, count: int = 0) -> typing.Iterator[munch.Munch]:
received = 0
with connection.pubsub() as subscriber:
subscriber.subscribe(channel)
while (received < count) or (count == 0):
message = subscriber.get_message(ignore_subscribe_messages=True)
if message is None:
continue
data = message.get("data")
if not data:
continue
yield munch.Munch(json.loads(data))
received += 1 But without this fix my function would loop without blocking. Currently I have to set the def receive_sync(channel: str = CHANNEL, connection: redis.Redis = REDIS_SYNC, count: int = 0) -> typing.Iterator[munch.Munch]:
received = 0
with connection.pubsub() as subscriber:
subscriber.subscribe(channel)
while (received < count) or (count == 0):
message = subscriber.get_message(ignore_subscribe_messages=True, timeout=1)
if message is None:
continue
data = message.get("data")
if not data:
continue
yield munch.Munch(json.loads(data))
received += 1 |
Ah yes, thank you for taking the time to explain! I'm not the original author of the code, but I disagree with
I don't think that there is anything indicating that get_message without parameters should be blocking, the documentation doesn't say that. Also, the fact that your change breaks a few tests is an indication that this behavior was intended. I agree that many APIs default to blocking behavior and, for this reason, one might intuitively expect this to work in a similar way without reading the doc, but this is the way it was written a long time ago. The only thing we can do is to make the documentation more explicit about get_message's behavior to avoid confusion. |
I understand. I think the documentation should be clearer. |
I crated an issue to track this #151 |
Pull Request check-list
Description of change
Fixed excessive CPU usage by changing the default timeout values from
0
to none.