Avoid unnecessary system calls in redisAsyncCommand()#1089
Avoid unnecessary system calls in redisAsyncCommand()#1089tezc wants to merge 1 commit intoredis:masterfrom
Conversation
|
This looks correct to me at first glance, although I didn't write the async layer. How big a performance improvement are you seeing with it, assuming you're using the new logic? |
|
Hi, @michael-grunder I see %2 - %20 improvement in my use case. (I use hiredis as part of a bigger project, so a loop benchmark with hiredis commands only probably would give us even better results). I'm pretty sure this is how we are supposed to use event loops. (Write to socket first, if it is partial, register for the write event). The downside is, now inside Edit: Maybe another side effect is about batching. Today, you can call |
|
@tezc I agree that generally, one should create the write event only after failing to write. In this specific case, I think it will take a bit more to handle it well. Invoking the disconnect callback directly from The other point is that the async interface does not have explicit pipelining support (like Another option to consider is to create a new |
|
I think the improvement is worth making, but we'll need to make sure not to introduce any breaking changes. I'm planning on putting together |
|
Okay, I'll see what I can do. Sure, we can revisit this later. |
Currently, this is how async operations work:
1- Append new command to the output buffer.
2- __redisAsyncCommand() registers write event unconditionally.
3- redisAsyncWrite() will be called on the next iteration of the event loop.
4- Write event will be cleared.
Steps 2 and 4 are system calls. They introduce unnecessary overhead.
For better performance, we can directly write to the socket(step-3)
without registering a write event. Still, it is better to detect if the write
event is already registered. In this case, we won't try to write to the socket
as it will probably fail (because the socket buffer is full).