Skip to content

Commit a64cba3

Browse files
committed
Rename --children to --subprocesses
1 parent bc5dc46 commit a64cba3

File tree

4 files changed

+56
-56
lines changed

4 files changed

+56
-56
lines changed

Doc/library/profiling.sampling.rst

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -310,8 +310,8 @@ The default configuration works well for most use cases:
310310
- Wall-clock mode (all samples recorded)
311311
* - ``--realtime-stats``
312312
- No live statistics display during profiling
313-
* - ``--children``
314-
- Profile only the target process (no child process monitoring)
313+
* - ``--subprocesses``
314+
- Profile only the target process (no subprocess monitoring)
315315

316316

317317
Sampling interval and duration
@@ -444,14 +444,14 @@ working correctly and that sufficient samples are being collected. See
444444
:ref:`sampling-efficiency` for details on interpreting these metrics.
445445

446446

447-
Child process profiling
448-
-----------------------
447+
Subprocess profiling
448+
--------------------
449449

450-
The :option:`--children` option enables automatic profiling of child processes
450+
The :option:`--subprocesses` option enables automatic profiling of subprocesses
451451
spawned by the target::
452452

453-
python -m profiling.sampling run --children script.py
454-
python -m profiling.sampling attach --children 12345
453+
python -m profiling.sampling run --subprocesses script.py
454+
python -m profiling.sampling attach --subprocesses 12345
455455

456456
When enabled, the profiler monitors the target process for child process
457457
creation. When a new Python child process is detected, a separate profiler
@@ -480,39 +480,39 @@ or other process spawning mechanisms.
480480
481481
::
482482

483-
python -m profiling.sampling run --children --flamegraph worker_pool.py
483+
python -m profiling.sampling run --subprocesses --flamegraph worker_pool.py
484484

485485
This produces separate flame graphs for the main process and each worker
486486
process: ``flamegraph.<main_pid>.html``, ``flamegraph.<worker1_pid>.html``,
487487
and so on.
488488

489-
Each child process receives its own output file. The filename is derived from
490-
the specified output path (or the default) with the child's process ID
489+
Each subprocess receives its own output file. The filename is derived from
490+
the specified output path (or the default) with the subprocess's process ID
491491
appended:
492492

493-
- If you specify ``-o profile.html``, children produce ``profile_12345.html``,
493+
- If you specify ``-o profile.html``, subprocesses produce ``profile_12345.html``,
494494
``profile_12346.html``, and so on
495-
- With default output, children produce files like ``flamegraph.12345.html``
495+
- With default output, subprocesses produce files like ``flamegraph.12345.html``
496496
or directories like ``heatmap_12345``
497-
- For pstats format (which defaults to stdout), children produce files like
497+
- For pstats format (which defaults to stdout), subprocesses produce files like
498498
``profile.12345.pstats``
499499

500-
The child profilers inherit most sampling options from the parent (interval,
500+
The subprocess profilers inherit most sampling options from the parent (interval,
501501
duration, thread selection, native frames, GC frames, async-aware mode, and
502502
output format). All Python descendant processes are profiled recursively,
503503
including grandchildren and further descendants.
504504

505-
Child process detection works by periodically scanning for new descendants of
505+
Subprocess detection works by periodically scanning for new descendants of
506506
the target process and checking whether each new process is a Python process.
507507
On Linux, this uses a fast check of the executable name followed by a full
508-
probe of the process memory if needed. Non-Python child processes (such as
508+
probe of the process memory if needed. Non-Python subprocesses (such as
509509
shell commands or external tools) are ignored.
510510

511-
There is a limit of 100 concurrent child profilers to prevent resource
511+
There is a limit of 100 concurrent subprocess profilers to prevent resource
512512
exhaustion in programs that spawn many processes. If this limit is reached,
513-
additional child processes are not profiled and a warning is printed.
513+
additional subprocesses are not profiled and a warning is printed.
514514

515-
The :option:`--children` option is incompatible with :option:`--live` mode
515+
The :option:`--subprocesses` option is incompatible with :option:`--live` mode
516516
because live mode uses an interactive terminal interface that cannot
517517
accommodate multiple concurrent profiler displays.
518518

@@ -1203,9 +1203,9 @@ Sampling options
12031203
Compatible with ``--live``, ``--flamegraph``, ``--heatmap``, and ``--gecko``
12041204
formats only.
12051205

1206-
.. option:: --children
1206+
.. option:: --subprocesses
12071207

1208-
Also profile child processes. Each child process gets its own profiler
1208+
Also profile subprocesses. Each subprocess gets its own profiler
12091209
instance and output file. Incompatible with ``--live``.
12101210

12111211

Lib/profiling/sampling/cli.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class CustomFormatter(
8989
def _setup_child_monitor(args, parent_pid):
9090
from ._child_monitor import ChildProcessMonitor
9191

92-
# Build CLI args for child profilers (excluding --children to avoid recursion)
92+
# Build CLI args for child profilers (excluding --subprocesses to avoid recursion)
9393
child_cli_args = _build_child_profiler_args(args)
9494

9595
# Build output pattern
@@ -103,7 +103,7 @@ def _setup_child_monitor(args, parent_pid):
103103

104104

105105
def _get_child_monitor_context(args, pid):
106-
if getattr(args, 'children', False):
106+
if getattr(args, 'subprocesses', False):
107107
return _setup_child_monitor(args, pid)
108108
return nullcontext()
109109

@@ -157,7 +157,7 @@ def _build_output_pattern(args):
157157
if args.format == "heatmap":
158158
return "heatmap_{pid}"
159159
if args.format == "pstats":
160-
# pstats defaults to stdout, but for children we need files
160+
# pstats defaults to stdout, but for subprocesses we need files
161161
return "profile.{pid}.pstats"
162162
return f"{args.format}.{{pid}}.{extension}"
163163

@@ -286,9 +286,9 @@ def _add_sampling_options(parser):
286286
help="Enable async-aware profiling (uses task-based stack reconstruction)",
287287
)
288288
sampling_group.add_argument(
289-
"--children",
289+
"--subprocesses",
290290
action="store_true",
291-
help="Also profile child processes. Each child gets its own profiler and output file.",
291+
help="Also profile subprocesses. Each subprocess gets its own profiler and output file.",
292292
)
293293

294294

@@ -490,10 +490,10 @@ def _validate_args(args, parser):
490490
"Live mode requires the curses module, which is not available."
491491
)
492492

493-
# --children is incompatible with --live
494-
if hasattr(args, 'children') and args.children:
493+
# --subprocesses is incompatible with --live
494+
if hasattr(args, 'subprocesses') and args.subprocesses:
495495
if hasattr(args, 'live') and args.live:
496-
parser.error("--children is incompatible with --live mode.")
496+
parser.error("--subprocesses is incompatible with --live mode.")
497497

498498
# Async-aware mode is incompatible with --native, --no-gc, --mode, and --all-threads
499499
if args.async_aware:

Lib/test/test_profiling/test_sampling_profiler/test_children.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Tests for --children subprocess profiling support."""
1+
"""Tests for --subprocesses subprocess profiling support."""
22

33
import argparse
44
import io
@@ -334,36 +334,36 @@ def test_context_manager(self):
334334
@skip_if_not_supported
335335
@requires_subprocess()
336336
class TestCLIChildrenFlag(unittest.TestCase):
337-
"""Tests for the --children CLI flag."""
337+
"""Tests for the --subprocesses CLI flag."""
338338

339339
def setUp(self):
340340
reap_children()
341341

342342
def tearDown(self):
343343
reap_children()
344344

345-
def test_children_flag_parsed(self):
346-
"""Test that --children flag is recognized."""
345+
def test_subprocesses_flag_parsed(self):
346+
"""Test that --subprocesses flag is recognized."""
347347
from profiling.sampling.cli import _add_sampling_options
348348

349349
parser = argparse.ArgumentParser()
350350
_add_sampling_options(parser)
351351

352-
# Parse with --children
353-
args = parser.parse_args(["--children"])
354-
self.assertTrue(args.children)
352+
# Parse with --subprocesses
353+
args = parser.parse_args(["--subprocesses"])
354+
self.assertTrue(args.subprocesses)
355355

356-
# Parse without --children
356+
# Parse without --subprocesses
357357
args = parser.parse_args([])
358-
self.assertFalse(args.children)
358+
self.assertFalse(args.subprocesses)
359359

360-
def test_children_incompatible_with_live(self):
361-
"""Test that --children is incompatible with --live."""
360+
def test_subprocesses_incompatible_with_live(self):
361+
"""Test that --subprocesses is incompatible with --live."""
362362
from profiling.sampling.cli import _validate_args
363363

364-
# Create mock args with both children and live
364+
# Create mock args with both subprocesses and live
365365
args = argparse.Namespace(
366-
children=True,
366+
subprocesses=True,
367367
live=True,
368368
async_aware=False,
369369
format="pstats",
@@ -500,7 +500,7 @@ def test_build_output_pattern_default(self):
500500
"Test requires process_vm_readv support on Linux",
501501
)
502502
class TestChildrenIntegration(unittest.TestCase):
503-
"""Integration tests for --children functionality."""
503+
"""Integration tests for --subprocesses functionality."""
504504

505505
def setUp(self):
506506
reap_children()
@@ -891,16 +891,16 @@ def test_wait_for_profilers_multiple(self):
891891
"Test requires process_vm_readv support on Linux",
892892
)
893893
class TestEndToEndChildrenCLI(unittest.TestCase):
894-
"""End-to-end tests for --children CLI flag."""
894+
"""End-to-end tests for --subprocesses CLI flag."""
895895

896896
def setUp(self):
897897
reap_children()
898898

899899
def tearDown(self):
900900
reap_children()
901901

902-
def test_children_flag_spawns_child_and_creates_output(self):
903-
"""Test that --children flag works end-to-end with actual subprocesses."""
902+
def test_subprocesses_flag_spawns_child_and_creates_output(self):
903+
"""Test that --subprocesses flag works end-to-end with actual subprocesses."""
904904
# Create a temporary directory for output files
905905
with tempfile.TemporaryDirectory() as tmpdir:
906906
# Create a script that spawns a child Python process
@@ -926,14 +926,14 @@ def test_children_flag_spawns_child_and_creates_output(self):
926926

927927
output_file = os.path.join(tmpdir, "profile.pstats")
928928

929-
# Run the profiler with --children flag
929+
# Run the profiler with --subprocesses flag
930930
result = subprocess.run(
931931
[
932932
sys.executable,
933933
"-m",
934934
"profiling.sampling",
935935
"run",
936-
"--children",
936+
"--subprocesses",
937937
"-d",
938938
"3",
939939
"-i",
@@ -971,8 +971,8 @@ def test_children_flag_spawns_child_and_creates_output(self):
971971
f"stdout: {result.stdout}, stderr: {result.stderr}"
972972
)
973973

974-
def test_children_flag_with_flamegraph_output(self):
975-
"""Test --children with flamegraph output format."""
974+
def test_subprocesses_flag_with_flamegraph_output(self):
975+
"""Test --subprocesses with flamegraph output format."""
976976
with tempfile.TemporaryDirectory() as tmpdir:
977977
# Simple parent that spawns a child
978978
parent_script = f"""
@@ -995,7 +995,7 @@ def test_children_flag_with_flamegraph_output(self):
995995
"-m",
996996
"profiling.sampling",
997997
"run",
998-
"--children",
998+
"--subprocesses",
999999
"-d",
10001000
"2",
10011001
"-i",
@@ -1024,8 +1024,8 @@ def test_children_flag_with_flamegraph_output(self):
10241024
"Flamegraph output should be HTML",
10251025
)
10261026

1027-
def test_children_flag_no_crash_on_quick_child(self):
1028-
"""Test that --children doesn't crash when child exits quickly."""
1027+
def test_subprocesses_flag_no_crash_on_quick_child(self):
1028+
"""Test that --subprocesses doesn't crash when child exits quickly."""
10291029
with tempfile.TemporaryDirectory() as tmpdir:
10301030
# Parent spawns a child that exits immediately
10311031
parent_script = f"""
@@ -1049,7 +1049,7 @@ def test_children_flag_no_crash_on_quick_child(self):
10491049
"-m",
10501050
"profiling.sampling",
10511051
"run",
1052-
"--children",
1052+
"--subprocesses",
10531053
"-d",
10541054
"2",
10551055
"-i",

Misc/NEWS.d/next/Library/2025-12-12-15-14-03.gh-issue-138122.m3EF9E.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Add ``--children`` flag to :mod:`profiling.sampling` CLI to automatically
2-
profile child processes spawned by the target. When enabled, the profiler
1+
Add ``--subprocesses`` flag to :mod:`profiling.sampling` CLI to automatically
2+
profile subprocesses spawned by the target. When enabled, the profiler
33
monitors for new Python subprocesses and profiles each one separately,
44
writing results to individual output files. This is useful for profiling
55
applications that use :mod:`multiprocessing`, :class:`~concurrent.futures.ProcessPoolExecutor`,

0 commit comments

Comments
 (0)