Mapped tasks for parallel processing in Apache Airflow - Time & Space Complexity
When using mapped tasks in Airflow, we want to know how the time to run tasks changes as we increase the number of items to process.
We ask: How does adding more items affect the total work done?
Analyze the time complexity of the following Airflow DAG snippet using mapped tasks.
from airflow import DAG
from airflow.decorators import task
from datetime import datetime
def process_item(item):
return item * 2
with DAG('mapped_task_dag', start_date=datetime(2024,1,1)) as dag:
@task
def multiply(item):
return process_item(item)
items = [1, 2, 3, 4, 5]
multiply.expand(item=items)
This code runs the process_item function on each item in the list in parallel using mapped tasks.
Look for repeated work inside the mapped task.
- Primary operation: Running
process_itemon each item. - How many times: Once per item in the input list.
Each new item adds one more task to run, so the total work grows directly with the number of items.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 tasks run |
| 100 | 100 tasks run |
| 1000 | 1000 tasks run |
Pattern observation: The work grows linearly as you add more items.
Time Complexity: O(n)
This means the total work increases in direct proportion to the number of items processed.
[X] Wrong: "Mapped tasks run all items instantly with no extra time as we add more items."
[OK] Correct: Each item still needs its own task to run, so more items mean more total work, even if tasks run in parallel.
Understanding how mapped tasks scale helps you explain how Airflow handles many parallel jobs efficiently, a useful skill for real-world workflows.
What if we changed the mapped task to process items sequentially inside one task? How would the time complexity change?
Practice
mapped tasks in Airflow?Solution
Step 1: Understand mapped tasks concept
Mapped tasks allow running multiple similar jobs at the same time using different inputs.Step 2: Compare options with concept
Only To run many similar tasks in parallel using a list of inputs describes running many similar tasks in parallel using a list of inputs, which matches mapped tasks.Final Answer:
To run many similar tasks in parallel using a list of inputs -> Option AQuick Check:
Mapped tasks = parallel jobs with input list [OK]
- Thinking mapped tasks run sequentially
- Confusing mapped tasks with scheduling frequency
- Assuming mapped tasks require manual triggers
Solution
Step 1: Recall the method to map tasks
In Airflow,.expand()is used to map tasks with a list of inputs.Step 2: Match syntax with options
Only task.expand(input_list=[1, 2, 3]) usestask.expand(input_list=[1, 2, 3]), which is correct syntax.Final Answer:
task.expand(input_list=[1, 2, 3]) -> Option DQuick Check:
Use .expand() to map tasks [OK]
- Using .map() instead of .expand()
- Calling .run_parallel() which does not exist
- Using .execute() with inputs incorrectly
def greet(name):
return f"Hello, {name}!"
mapped_task = greet.expand(name=["Alice", "Bob", "Carol"])Solution
Step 1: Understand .expand() behavior
The .expand() method runs the function for each item in the list separately, producing a list of results.Step 2: Apply greet function to each name
For names "Alice", "Bob", and "Carol", greet returns "Hello, Alice!", "Hello, Bob!", and "Hello, Carol!" respectively.Final Answer:
["Hello, Alice!", "Hello, Bob!", "Hello, Carol!"] -> Option AQuick Check:
.expand() applies function to each input [OK]
- Thinking .expand() passes whole list as one input
- Expecting repeated output for first input only
- Assuming .expand() causes an error on functions
def process(item):
return item * 2
mapped_task = process.expand(items=[1, 2, 3])Solution
Step 1: Check function parameter and expand argument
The function parameter is nameditem, but expand usesitems. They must match.Step 2: Understand expand() argument matching
expand() requires the argument name to match the function parameter exactly to map inputs correctly.Final Answer:
The argument name in expand() should match the function parameter -> Option BQuick Check:
expand() argument name = function parameter [OK]
- Using different names for expand() argument and function parameter
- Thinking function cannot return values
- Believing expand() can't use lists
- Forgetting @task decorator (not always required)
def process_user(user_id):
return f"Processed {user_id}"
user_ids = [5, 12, 7, 20, 15]
# Which line correctly maps filtered user_ids?Solution
Step 1: Filter user_ids list correctly
Use a list comprehension to select IDs greater than 10:[uid for uid in user_ids if uid > 10].Step 2: Pass filtered list to expand()
Pass the filtered list as the argument toexpand()matching the function parameter name.Final Answer:
mapped_task = process_user.expand(user_id=[uid for uid in user_ids if uid > 10]) -> Option CQuick Check:
Filter with list comprehension before expand() [OK]
- Using .filter() or .map() which are not list methods
- Trying to compare list directly to number
- Passing boolean list instead of filtered values
Ready to prove it?
Pass the test and this pattern moves unknown
