Skip to content

feat: add MBResourceUsage mixin with POSIX getrusage() capture #110

Open
alubbock wants to merge 10 commits intomainfrom
feat/resource-usage-mixin
Open

feat: add MBResourceUsage mixin with POSIX getrusage() capture #110
alubbock wants to merge 10 commits intomainfrom
feat/resource-usage-mixin

Conversation

@alubbock
Copy link
Copy Markdown
Owner

On POSIX, records user/system CPU time, peak RSS (normalised to bytes),
minor/major page faults, block I/O ops, and voluntary/involuntary
context switches via the stdlib resource module.

CLI mode uses os.wait4() which calculates per subprocess run;
Python API mode uses RUSAGE_SELF. maxrss is intentionally
omitted here as it's a high watermark for the entire Python
process lifetime.

On Windows, the mixin records an empty dict silently.

Added as a default CLI mixin in _DEFAULT_MIXINS.

alubbock added 10 commits March 19, 2026 10:30
Records user/system CPU time, peak RSS (normalised to bytes),
minor/major page faults, block I/O ops, and voluntary/involuntary
context switches via the stdlib resource module.

CLI mode uses RUSAGE_CHILDREN (subprocess resources, before/after
delta); Python API mode uses RUSAGE_SELF. maxrss is taken from
the post-run snapshot directly (it's a high-water mark, not an
accumulator). On Windows the mixin records an empty dict silently.

Added as a default CLI mixin in _DEFAULT_MIXINS.
… API modes

CLI tests: default inclusion, all 9 fields present and numeric,
--no-mixin exclusion, --show-mixins marker, and three real-subprocess
tests (maxrss > 0, cpu non-negative, counts non-negative).

Python API tests: all 9 fields present, maxrss positive and int,
utime/stime non-negative, counts non-negative, and Windows fallback
(resource=None records empty dict).

POSIX-only tests are marked skipif(sys.platform == 'win32').
- cli.md: update default-mixins paragraph to include resource-usage,
  add resource-usage options section (no flags, Windows note)
- mixins.md: add MBResourceUsage to the reference table, update CLI
  defaults paragraph, add full MBResourceUsage section (modes, fields
  table, platform note, macOS zero-counter note, CLI usage)
- CHANGELOG.md: add [Unreleased] entry for MBResourceUsage
…n CLI mode

- _rusage_to_dict: add include_maxrss kwarg; omit maxrss key when False
- _rusage_delta: delta maxrss like all other fields (was: post-run value
  directly), making multi-iteration CLI runs report honest 0 when a child
  does not exceed the prior RUSAGE_CHILDREN high-water mark
- MBResourceUsage: capture/capturepost methods split on CLI vs Python API
  mode; Python API omits maxrss because RUSAGE_SELF.maxrss is a lifetime
  process HWM and cannot isolate a single function call
- Comprehensive docstring with per-field mode table and platform quirks
- docs/user-guide/mixins.md: rewritten MBResourceUsage section with
  separate JSON examples per mode, per-field Modes column, and full
  platform notes (maxrss multi-iteration caveat, inblock/oublock macOS,
  majflt macOS, os.wait4 follow-up)
- CHANGELOG.md: promote [Unreleased] to [2.1.0] - 2026-03-19
- docs/cli.md: minor wording tweak (Python resource module)
- Rename _RUSAGE_FIELDS to _RUSAGE_FIELDS_PYTHON_API (8 fields, no maxrss)
- Replace test_resource_usage_python_api_maxrss_positive with
  test_resource_usage_python_api_maxrss_absent: asserts maxrss key is
  absent from Python API mode resource_usage records
- CLI tests (_RUSAGE_FIELDS with maxrss) unchanged — CLI mode still
  records maxrss via RUSAGE_CHILDREN
…r-child rusage

- CLI mode uses os.wait4() (all POSIX) to record exact rusage for each
  child process; one entry per timed iteration aligned with call.durations.
  Falls back to RUSAGE_CHILDREN delta on Windows; maxrss stripped when
  warmup>0 or iterations>1 to avoid misleading cumulative HWM values.
- Python API mode records a single aggregate RUSAGE_SELF delta across all
  iterations (list always has one entry). Dropped pre/post_run_triggers
  approach due to MRO ordering issue with MicroBenchBase.
- resource_usage changed from dict to list[dict] in all modes.
- Tests, docs, and CHANGELOG updated accordingly.
…simplify

All platforms with the stdlib resource module also have os.wait4(), so
the _HAVE_WAIT4=False + resource-available code path could never fire.

- Remove _HAVE_WAIT4 flag from cli/main.py and mixins/system.py
- Remove RUSAGE_CHILDREN before/after delta fallback in cli/main.py
- Remove maxrss-stripping logic in capturepost_resource_usage
- Re-raise os.wait4() errors instead of silently falling back
- Rewrite CLI test mocking to use os.wait4() instead of _HAVE_WAIT4=False
- Update docs to remove Windows-specific fallback narrative
Without a try/finally, an unexpected BaseException (including
KeyboardInterrupt during os.wait4 thread join) would leave the child
running as an orphan and leak the stdout/stderr pipe file descriptors.

- Wrap the post-Popen block in try/except BaseException to kill and
  reap the child on any unexpected exception before re-raising
- Add a finally block that always closes proc.stdout / proc.stderr
- Replace raw iter() in _make_mock_popen and one test with _MockPipe,
  a minimal closeable wrapper, so the finally block works correctly
  in tests
- Add test_cli_keyboard_interrupt_kills_child: verifies kill()/wait()
  are called and KeyboardInterrupt propagates
- Add test_cli_pipe_fds_closed_after_run: verifies pipe FDs are closed
  after a normal run
…ndler

test_cli_keyboard_interrupt_kills_child covers this branch; the pragma
was added before that test existed and should not suppress coverage.
…API mode

Add cooperative super() forwarding to MicroBenchBase.pre_run_triggers and
post_run_triggers so mixin overrides are reached despite the base class
appearing before mixin classes in the MRO. MBResourceUsage uses these hooks
to snapshot RUSAGE_SELF before and after each individual call, appending a
per-iteration delta to resource_usage rather than a single aggregate across
all iterations.

resource_usage now aligns index-for-index with call.durations in both CLI
and Python API mode. Warmup calls are excluded in both modes.
@alubbock alubbock force-pushed the feat/resource-usage-mixin branch from ea09c0d to 03d132f Compare March 19, 2026 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant