Skip to content

Restore mp_start_method config and add mp_forkserver_preload config#68875

Merged
vatsrahul1001 merged 3 commits into
apache:mainfrom
jason810496:feature/airflow-core/restore-mp-start-method
Jun 23, 2026
Merged

Restore mp_start_method config and add mp_forkserver_preload config#68875
vatsrahul1001 merged 3 commits into
apache:mainfrom
jason810496:feature/airflow-core/restore-mp-start-method

Conversation

@jason810496

@jason810496 jason810496 commented Jun 23, 2026

Copy link
Copy Markdown
Member

Why

Python 3.14 changed the Unix (non-macOS) default multiprocessing start method from fork to forkserver (python/cpython#84559).

  • forkserver/spawn children re-import Airflow instead of sharing it copy-on-write, so the scheduler's LocalExecutor workers and the triggerer each pay for a private copy.
  • Benchmarking the upgrade from Airflow 3.2.2 / Python 3.13.14 (fork default) to 3.3.0b1 / Python 3.14.6 (forkserver default) measured steady-state PSS (Proportional Set Size, the copy-on-write-aware resident memory metric) up +96% for the scheduler and +90% for the triggerer; setting mp_start_method = fork for the scheduler and triggerer on the new stack brings them back to +17% / +20% of that baseline.

This restores control over the start method so deployments can recover the pre-3.14 footprint. It is opt-in: unset keeps the platform default, so there is no behaviour change unless configured.

What

  • Add [core] mp_start_method (overridable per component via [scheduler], [triggerer] or [dag_processor]) and [core] mp_forkserver_preload.
  • Add resolve_mp_start_method / set_component_mp_start_method to process_utils; the latter applies the configured method and forkserver preload modules, and is a safe no-op when unset or when the method is unavailable on the platform.
  • Call set_component_mp_start_method from the scheduler, triggerer and dag-processor CLI entrypoints, before any multiprocessing work.
  • Resolve LocalExecutor.is_mp_using_fork per instance instead of once at import, so it honours a start method set by the CLI before the executor is created.

Note: [core] mp_start_method existed historically but was removed (functional part in #48817, config remnants in #61150) and only ever governed the pre-3.0 Dag-processing manager, never LocalExecutor. The version restored here is wired into the executor and component start paths so it actually controls the workers.

Scheduler / triggerer memory benchmark — patch-mode summary

Modes: baseline (no patch) | gc (periodic gc.collect) | fspreload (forkserver + set_forkserver_preload) | fork (set_start_method fork) | gc_fspreload / gc_fork (combinations) | forkserver (forkserver, no preload).

Permutation setup & effective start method

Reference baseline (Δ denominator): 3.2.2 / py3.13.14 (baseline).

  • forkserver preload list: airflow,airflow.models,airflow.executors.local_executor,airflow.sdk,sqlalchemy,pydantic
# airflow python mode sched cfg trig cfg preload sched live trig live dfp live
1 3.2.2 3.13.14 baseline unset unset fork fork fork
2 3.3.0b1 3.14.6 baseline unset unset forkserver forkserver forkserver
3 3.3.0b1 3.14.6 fork fork fork fork fork forkserver
4 3.3.0b1 3.14.6 fspreload forkserver forkserver 6 mods forkserver forkserver forkserver
5 3.3.0b1 3.14.6 forkserver forkserver forkserver forkserver forkserver forkserver

Steady-state PSS (MB), Δ vs the reference baseline

# airflow python mode sched PSS Δ sched sched n trig PSS Δ trig trig n dfp PSS dfp n samples
1 3.2.2 3.13.14 baseline 400.7 ref 10 198.6 ref 3 137.6 1 10
2 3.3.0b1 3.14.6 baseline 784.8 +96% 12 376.9 +90% 5 166.0 1 10
3 3.3.0b1 3.14.6 fork 467.5 +17% 10 238.7 +20% 3 166.3 1 10
4 3.3.0b1 3.14.6 fspreload 690.8 +72% 12 380.2 +91% 5 166.0 1 10
5 3.3.0b1 3.14.6 forkserver 783.4 +96% 12 376.6 +90% 5 165.9 1 10

Per-stack mitigation (Δ vs each stack's own baseline)

The headline table above is vs the pre-regression reference. These pivots instead show each patch mode vs that same stack's baseline column, i.e. the mitigation effect on the PR stack itself (fork/fspreload/forkserver vs the unset run on 3.3.0b1/3.14.6).

How to read this

  • sched/trig live must equal the configured method (fork/forkserver) and dfp live must stay at the platform default — that proves the per-component config took effect only where set.
  • In the headline table, fork should pull the scheduler & triggerer back near the 3.2.2/3.13.14 reference (Δ ~0), while the unset/forkserver runs stay well above it (the forkserver regression); fspreload lands in between (helps the scheduler, less the triggerer).
  • The dag-processor PSS should be flat across every run (raw os.fork, untouched).

Was generative AI tooling used to co-author this PR?

Comment thread airflow-core/src/airflow/cli/commands/api_server_command.py Outdated
@jason810496 jason810496 requested review from kaxil and uranusjr June 23, 2026 09:27
@jason810496 jason810496 self-assigned this Jun 23, 2026
@vatsrahul1001 vatsrahul1001 added this to the Airflow 3.3.0 milestone Jun 23, 2026

@jason810496 jason810496 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found the typo in the last sec, I should use claude to remove the API section out (I did it manually) then.

Comment thread airflow-core/src/airflow/config_templates/config.yml Outdated
Comment thread airflow-core/src/airflow/config_templates/config.yml Outdated

@amoghrajesh amoghrajesh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description mentions [api] as a configurable component but I dont seem to find it there? Either wire it up or drop [api] from the description and config docs.

Comment thread airflow-core/tests/unit/utils/test_process_utils.py
Comment thread airflow-core/src/airflow/utils/process_utils.py
@jason810496 jason810496 force-pushed the feature/airflow-core/restore-mp-start-method branch from aaa07b4 to 9403aa4 Compare June 23, 2026 12:07
@vatsrahul1001 vatsrahul1001 merged commit 92290db into apache:main Jun 23, 2026
145 checks passed
cetingokhan pushed a commit to cetingokhan/airflow that referenced this pull request Jun 24, 2026
…pache#68875)

* Restore mp_start_method config and add mp_forkserver_preload config

* Remove set_component_mp_start_method for API server

* Spec multiprocessing mocks and cover start-method failure path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants