Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I make a fast operation async if the method is already async

I have this code (the unimportant details are that it runs on EC2 instances in AWS, processing messages on an SQS queue).

The first statement in the method gets some data over http, the second statement saves state to a local dynamo data store.

public bool HandleMessage(OrderAcceptedMessage message)
{
    var order = _orderHttpClient.GetById(message.OrderId);
    _localDynamoRepo.SaveAcceptedOrder(message, order);
    return true;
}

The performance characteristics are that the http round trip takes 100-200 milliseconds, and the dynamo write takes around 10 milliseconds.

Both of these operations have async versions. We could write it as follows:

public async Task<bool> HandleMessage(OrderAcceptedMessage message)
{
    var order = await _orderHttpClient.GetByIdAsync(message.OrderId);
    await _localDynamoRepo.SaveAcceptedOrderAsync(message, order);
    return true;
}

So the guidance is that since the first operation "could take longer than 50 milliseconds to execute" it should make use of async and await. (1)

But what about the second, fast operation? Which of these two arguments is correct:

Do not make it async: It does not meet the 50ms criterion and it's not worth the overhead.

Do make it async: The overhead has already been paid by the previous operation. There is already task-based asynchrony happening and it's worth using it.

1) http://blog.stephencleary.com/2013/04/ui-guidelines-for-async.html

like image 530
Anthony Avatar asked Jun 30 '16 08:06

Anthony


2 Answers

the unimportant details are that it runs on EC2 instances in AWS, processing messages on an SQS queue

Actually, I think that's an important detail. Because this is not a UI application; it's a server application.

the guidance is that since the first operation "could take longer than 50 milliseconds to execute"

This guidance only applies to UI applications. Thus, the 50ms guideline is meaningless here.

Which of these two arguments is correct

Asynchrony is not about speed. It's about freeing up threads. The 50ms guideline for UI apps is all about freeing up the UI thread. On the server side, async is about freeing up thread pool threads.

The question is how much scalability do you want/need? If your backend is scalable, then I generally recommend async, because that frees up thread pool threads. This makes your web app more scalable and more able to react to changes in load more quickly. But this only gives you a benefit if your backend can scale along with your web app.

like image 91
Stephen Cleary Avatar answered Sep 28 '22 01:09

Stephen Cleary


First notice that in web apps the biggest cost of async is reduction of productivity. This is what we are weighing the benefits against. You need to think about how much code will be infected if you make this one method async.

The benefit is saving a thread for the duration of the call. A 200ms HTTP call is a pretty good case for async (although it's impossible to say for sure because it also depends on how often you perform the call).

The 50ms criterion is not hard number. In fact that recommendation is for realtime UI apps.

A more useful number is latency times frequency. That tells you how many threads are consumed in the long term average. Infrequent calls do not need to be optimized.

100 dynamo calls per second at 10ms come out at one thread blocked. This is nothing. So this probably is not a good candidate for async.

Of course if you make the first call async you can make the second one async as well at almost no incremental productivity cost because everything is infected already.

You can run the numbers yourself and decide based on that.

like image 20
usr Avatar answered Sep 28 '22 02:09

usr