libuv combines mutliple async calls and invokes callback once

752 Views Asked by At

Requirement : A UDP server that on receiving an UDP packet and stores the received packet to one of the two queues. A worker thread is associated with each queue, and the associated thread picks up packet from the front of the queue, processes it and writes it into a in-memory cache system.

Constraints : solution has to be based on event-loop(libuv) and written in C

My Solution

  • register a call-back for incoming UDP which adds the received packet to one of the two queues and raises a uv_async_send

  • two global uv_sync_t objects are created one for each queue and used as parameter for uv_async_send. For ex : if packet is added to queue-one then uv_sync_t object-1 is used as parameter for uv_async_send. Similarly, if packet is added to queue-two then uv_sync_t object-2 is used

  • two threads are started, each having their own loop and a handle bound with a callback

    • In thread-one uv_sync_t object-1 is bound against a function (say funcA). In thread-two uv_sync_t object-2 is bound against another function (say funcB)
    • funcA and funcB reads "SINGLE" packet from corresponding queue and stores it in the in-memory cache

The problem The Client sends large number of packets which registers large number of events in the server. Now the problem is that libuv combines multiple calls into one and invokes a single callback(which removes a SINGLE node from queue). This leads to situation where nodes are being added to the queue at a faster rate and removed at a very slow rate. Can these rates be balanced ?

Is there a better way to design the server using event-looping library libuv ?

1

There are 1 best solutions below

0
On

Since you are queueing the packets in one thread but processing in another, it's possible that they work at slightly different rates. I'd use a thread-safe queue (have a look at concurrencykit.org) and process the entire queue on the async callback, instead of just processing a single packet.