lexeme
lexeme

Reputation: 2973

What is the benefit of mixing io-bound and cpu bound operations

This is the excerpt of the sign-in operation in Asp.Net Identity:

protected virtual async Task<PasswordVerificationResult> VerifyPasswordAsync(IUserPasswordStore<TUser> store, TUser user, string password)
{
    var hash = await store.GetPasswordHashAsync(user, CancellationToken);
    if (hash == null)
    {
        return PasswordVerificationResult.Failed;
    }

    return PasswordHasher.VerifyHashedPassword(user, hash, password);
}
  1. The VerifyHashedPassword(...) method is CPU-bound and is blocking. Is there any benefit of using the async GetPasswordHashAsync(...) call if VerifyHashedPassword(...) depends on its result?
  2. Shouldn't the await Task.Run(() => DoSomeWork()); construction be used instead (if inside the controller action)?

Upvotes: 0

Views: 574

Answers (2)

Martin Liversage
Martin Liversage

Reputation: 106806

PasswordHasher.VerifyHashedPassword is CPU bound to make it harder to guess a password and there is nothing you can do about it. Every login attempt will consume CPU cycles on the server.

However, doing I/O can be improved by using async and await. This will allow the thread waiting for store.GetPasswordHashAsync to process other work while the response is returned from the database.

So there is a benefit to using async and await but this benefit is not related to the password verification algorithm. And you cannot improve on that by starting a new task. That will just add overhead and that will be detrimental to performance.

Upvotes: 1

Darin Dimitrov
Darin Dimitrov

Reputation: 1038710

  1. The VerifyHashedPassword(...) method is CPU-bound and is blocking. Is there any benefit of using the async GetPasswordHashAsync(...) call if VerifyHashedPassword(...) depends on its result?

It makes strictly no sense to use async for CPU bound operations. You will just make things worse, believe me. Or if you don't believe me, measure.

  1. Shouldn't the await Task.Run(() => DoSomeWork()); construction be used instead (if inside the controller action)?

Of course not. Don't try to mask one problem by creating another one. By starting a new task you are jeopardizing the available tasks for serving other requests and most probably getting worse throughput compared to the sync version.

The magic rule of thumb to follow: use async only for I/O bound operations where you can get the enormous benefit of I/O Completion Ports built into the Windows Operating System. Basically if at the end of the day you don't hit an IOCP you are making things worse with all those tasks.

For everything else, you are basically shooting yourself into the feet.

Upvotes: 2

Related Questions