Does the order of awaited statements matter in Python when combined with synchronous calls?

Does it make sense to move operations that can be awaited to the top of a method to be able to do work while they are being awaited?

Example

in logical order

async def set_new_password(user_id, new_password):
    hash = bcrypt(new_password)
    db_handle = await async_get_db_handle()
    await async_write_password(db_handle, user_id, hash)

Here afaiu Python will calculate the hash, then create the coroutine for the db handle, then the coroutine for the write operation and then give control to the event loop that will schedule both operations.

In that case, assuming this is our only method call, we "wasted" time hashing the password, and the following would be faster.

synchronous as late as possible

async def set_new_password(user_id, new_password):
    db_handle = await async_get_db_handle()
    hash = bcrypt(new_password)
    await async_write_password(dh_handle, user_id, hash)

Here while the db_handle is awaited the password would be hashed, so we would use the "down time" to do something useful.

So should I aspire to always put not-awaitable statements as late as possible so that they can be executed while awaitable statements are awaited?

Upvotes: 4

Views: 212

Answers (1)

Martin Stone
Martin Stone

Reputation: 13007

... while the db_handle is awaited the password would be hashed, so we would use the "down time" to do something useful.

I don't think this is correct. The effect of await is to prevent the next line from executing until the db_handle is returned. It makes the calling code behave like synchronous code, so the normal ordering considerations apply.

If you want to do some work while getting the handle you could use a Task.

async def set_new_password(user_id, new_password):
    task = asyncio.create_task(get_db_handle())
    hash = bcrypt(new_password)
    db_handle = await task
    await async_write_password(db_handle, user_id, hash)

Upvotes: 5

Related Questions