4

I have a queue processor that is retrieving all messages from a ServiceBus Queue. I am wondering how I should determine the MessageReceiver PrefetchCount and the ReceiveBatch messageCount to optimize performance. I am currently setting these to the arbitrary number 500, as seen below:

var receiverFactory = MessagingFactory.CreateFromConnectionString("ConnectionString");
var receiver = await receiverFactory.CreateMessageReceiverAsync("QueueName", ReceiveMode.PeekLock);
receiver.PrefetchCount = 500;

bool loopBatch = true;
while (loopBatch) 
{
    var tempMessages = await receiver.ReceiveBatchAsync(500, TimeSpan.FromSeconds(1));
    // Do some message processing...
    loopBatch = tempMessages.Any();
}

When running, I see that my batches often take time to "warm up," retrieving counts such as "1, 1, 1, 1, 1, 1, 1, 1, 125, 125, 125, 125..." where the batch retrieval number suddenly jumps much higher.

From the Prefetching optimization docs:

When using the default lock expiration of 60 seconds, a good value for SubscriptionClient.PrefetchCount is 20 times the maximum processing rates of all receivers of the factory. For example, a factory creates 3 receivers, and each receiver can process up to 10 messages per second. The prefetch count should not exceed 20 X 3 X 10 = 600. By default, QueueClient.PrefetchCount is set to 0, which means that no additional messages are fetched from the service.

I don't really understand how to determine the receiver's "messages per second" when the batch retrieval seems to retrieve widely-varying numbers of messages at a time. Any assistance would be greatly appreciated.

ElliotSchmelliot
  • 7,322
  • 4
  • 41
  • 64

1 Answers1

4

I don't really understand how to determine the receiver's "messages per second" when the batch retrieval seems to retrieve widely-varying numbers of messages at a time.

Prefetch makes more sense in the scenario when OnMessage API is used. In that scenario a callback is registered that takes a single message for processing and you can estimate an average processing time of that message. OnMessage API allows to define how many concurrent callback will be running. It would be extremely innefficient to retrieve messages one by one knowing there is a constant flow of incoming messages. Hence, PrefetchCount is used to specify how many mesasges should be retrieved in a "batch" by clients in the background to save the roundtrips back to the server.

Sean Feldman
  • 23,443
  • 7
  • 55
  • 80
  • 1
    Sean, also you need to choose carefully the prefetch count based on the lock duration. When you prefetch messages, messages are locked and loaded into memory. Imagine you have prefetch count = 5. it takes 1 minute to process the 4 first messages. basically you wont be able to complete the last message because you've lost the lock. you need a combination between autorenewlock, lockduration, time to process a message, number of worker. it is very specific in fact – Thomas Feb 11 '18 at 23:05
  • Indeed. Lock cannot be extended for prefetched messages that didn't get to be processed and lock time has expired. It's a delicate balance of trying and figuring out numbers that work well. – Sean Feldman Feb 12 '18 at 00:39
  • Are you saying that PrefetechCount should not be used in the case where I am already using ReceiveBatch rather than OnMessage? Or can there still be some benefit to preloading in this case as well? – ElliotSchmelliot Feb 12 '18 at 20:09
  • PrefetchCount might do something when ReceiveBatch is used, for example if your batch is smaller than the maximum messages size and there's enough to pre-fetch. But if your batch is large than what's available or there's no constant stream of messages, it might be unutilized. Unfortunately, this is not so well documented and is a broker side knowledge. Perhaps worth raising with the [messaging team](https://github.com/Azure/azure-service-bus/issues) labeled as `documentation`/`server`. – Sean Feldman Feb 12 '18 at 21:43
  • Looks like documentation was updated, with a new section on [Prefetching and ReceiveBatch](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-performance-improvements?tabs=net-standard-sdk-2#prefetching-and-receivebatch) – ElliotSchmelliot Apr 12 '21 at 19:00