There are a number of problems with the queuing system that might be contributing to this. My experience is with an older version, but I think they are still true.
Firstly, you have to understand that agents don’t find calls, but rather calls find agents, and they only try to do so once every second. Note, when I say agent, the actual Asterisk terminology is “member”.
They can’t so so whilst they are outputting a comfort message, so if an agent becomes available during such a message, the call’s turn can be missed.
Next, if you have multiple queues sharing the same agent, a new arrival in one queue, if it is at the top of the queue, has an equal chance of grabbing an agent as one that has been waiting for a long time in another queue.
Also, if you use queue weights, the search for calls with a better call on an agent doesn’t go deep enough and doesn’t allow for the possibility that the same set of agents may be in multiple higher weight queues.
Finally the code that implements queue weights can take significant fractions of a second to run, if there are a lot of queues and agents.