In Python async function, how to calculate time consumed by overlapped blocking operation and non-blocking operation?

27 views Asked by At

I'm working with an asynchronous Python program that schedules three coroutines. Each coroutine involves:

  1. A blocking operation that takes X seconds (denoted as X_i for the i-th coroutine).
  2. A non-blocking operation that (ideally) doesn't block other tasks and takes Y seconds (denoted as Y_i for the i-th coroutine).
  3. A final blocking operation that takes Z seconds (denoted as Z_i for the i-th coroutine).

My question is:

What mathematical equation can represent the total execution time (T) of the program considering these individual task times (X_i, Y_i, and Z_i)?

import asyncio
import time
import random

async def fetch_data(data: str, delay: int) -> str:
    print('Fetching data...')
    await asyncio.sleep(delay)
    print(f'Data fetched successfully! with a non-blocking delay of {delay} seconds')
    return data

async def process_data(i: int, block_delay_1st: int, block_delay_2nd: int, non_block_delay: int=2):
    '''
    Coroutine: Represents a task that consists of X seconds of blocking operation,
    , Y seconds of awaitable operation, and finally Z seconds of blocking operation.
    '''
    print(f"Processing task-{i}... Block delay 1st: {block_delay_1st}, Non-block delay: {non_block_delay}, Block delay 2nd: {block_delay_2nd}")
    start_time = time.time()  # Start the timer
    time.sleep(block_delay_1st)
    await fetch_data("data_str", non_block_delay)
    time.sleep(block_delay_2nd)
    end_time = time.time()  # End the timer
    print(f"Task-{i} processed successfully! It takes: {end_time - start_time} seconds")

async def main():
    block_delay_dict = {1: (random.choice([1, 2, 3]), random.choice([1, 2, 3]), random.choice([1, 2, 3])),
                        2: (random.choice([1, 2, 3]), random.choice([1, 2, 3]), random.choice([1, 2, 3])),
                        3: (random.choice([1, 2, 3]), random.choice([1, 2, 3]), random.choice([1, 2, 3]))}
    tasks = [process_data(i, delay_1st, delay_2nd, non_block_delay) for i, (delay_1st, delay_2nd, non_block_delay) in block_delay_dict.items()]
    await asyncio.gather(*tasks)

if __name__ == "__main__":
    '''
    Total time spend will be T ≈ X1 + X2 + X3 + max(Y1, Y2, Y3) + Z1 + Z2 + Z3 ???
    '''
    start = time.perf_counter()
    asyncio.run(main())
    end = time.perf_counter()
    print(f"Execution time: {end - start} seconds")
0

There are 0 answers