abench 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- abench-0.1.0/.github/workflows/ci.yml +69 -0
- abench-0.1.0/.github/workflows/publish.yml +61 -0
- abench-0.1.0/.pre-commit-config.yaml +13 -0
- abench-0.1.0/LICENSE +29 -0
- abench-0.1.0/MANIFEST.in +4 -0
- abench-0.1.0/PKG-INFO +381 -0
- abench-0.1.0/README.md +351 -0
- abench-0.1.0/RELEASING.md +52 -0
- abench-0.1.0/examples/sandag-chunked.yaml +33 -0
- abench-0.1.0/pyproject.toml +54 -0
- abench-0.1.0/setup.cfg +4 -0
- abench-0.1.0/src/abench/Dockerfile +10 -0
- abench-0.1.0/src/abench/__init__.py +3 -0
- abench-0.1.0/src/abench/__main__.py +3 -0
- abench-0.1.0/src/abench/attempts.py +66 -0
- abench-0.1.0/src/abench/cli.py +563 -0
- abench-0.1.0/src/abench/common.py +22 -0
- abench-0.1.0/src/abench/experiments.py +269 -0
- abench-0.1.0/src/abench/failures.py +103 -0
- abench-0.1.0/src/abench/flow_cache.py +65 -0
- abench-0.1.0/src/abench/profiles/mtc.yaml +46 -0
- abench-0.1.0/src/abench/profiles/sandag.yaml +65 -0
- abench-0.1.0/src/abench/profiles.py +139 -0
- abench-0.1.0/src/abench/report.py +483 -0
- abench-0.1.0/src/abench/runtime/__init__.py +1 -0
- abench-0.1.0/src/abench/runtime/build_sources.py +109 -0
- abench-0.1.0/src/abench/runtime/cache_identity.py +37 -0
- abench-0.1.0/src/abench/runtime/instrumentation.py +79 -0
- abench-0.1.0/src/abench/runtime/worker.py +318 -0
- abench-0.1.0/src/abench/sources.py +93 -0
- abench-0.1.0/src/abench.egg-info/PKG-INFO +381 -0
- abench-0.1.0/src/abench.egg-info/SOURCES.txt +48 -0
- abench-0.1.0/src/abench.egg-info/dependency_links.txt +1 -0
- abench-0.1.0/src/abench.egg-info/entry_points.txt +2 -0
- abench-0.1.0/src/abench.egg-info/requires.txt +9 -0
- abench-0.1.0/src/abench.egg-info/top_level.txt +1 -0
- abench-0.1.0/tests/fixtures/tiny/benchmark.yaml +20 -0
- abench-0.1.0/tests/fixtures/tiny/configs/settings.yaml +15 -0
- abench-0.1.0/tests/fixtures/tiny/data/households.csv +5 -0
- abench-0.1.0/tests/fixtures/tiny/tiny_extension.py +76 -0
- abench-0.1.0/tests/requirements.txt +6 -0
- abench-0.1.0/tests/test_attempts.py +84 -0
- abench-0.1.0/tests/test_builder.py +82 -0
- abench-0.1.0/tests/test_docker.py +156 -0
- abench-0.1.0/tests/test_experiments.py +181 -0
- abench-0.1.0/tests/test_failure_diagnostics.py +109 -0
- abench-0.1.0/tests/test_flow_cache.py +98 -0
- abench-0.1.0/tests/test_measurement.py +364 -0
- abench-0.1.0/tests/test_profiles_sources.py +191 -0
- abench-0.1.0/tests/test_warmup.py +74 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
pull_request:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
workflow_call:
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
concurrency:
|
|
10
|
+
group: tests-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
jobs:
|
|
13
|
+
unit:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python: ['3.10', '3.11', '3.12']
|
|
19
|
+
timeout-minutes: 20
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python }}
|
|
25
|
+
cache: pip
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: '22'
|
|
29
|
+
- run: python -m pip install '.[test]' -r tests/requirements.txt
|
|
30
|
+
- run: ruff check . && ruff format --check .
|
|
31
|
+
- run: python -m pytest -m 'not docker' -q
|
|
32
|
+
- run: python -m build
|
|
33
|
+
- name: Verify installed wheel and packaged resources
|
|
34
|
+
run: |
|
|
35
|
+
python -m venv /tmp/abench-wheel
|
|
36
|
+
/tmp/abench-wheel/bin/pip install dist/*.whl
|
|
37
|
+
cd /tmp
|
|
38
|
+
/tmp/abench-wheel/bin/abench --help
|
|
39
|
+
/tmp/abench-wheel/bin/python -c "from pathlib import Path; import abench; p=Path(abench.__file__).parent; assert (p/'Dockerfile').is_file(); assert (p/'profiles/mtc.yaml').is_file(); assert (p/'runtime/build_sources.py').is_file()"
|
|
40
|
+
docker:
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
timeout-minutes: 30
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: '3.11'
|
|
48
|
+
cache: pip
|
|
49
|
+
- run: python -m pip install . pytest
|
|
50
|
+
- name: Build exact sources and exercise serial and multiprocess runs
|
|
51
|
+
env:
|
|
52
|
+
ABENCH_DOCKER_TESTS: '1'
|
|
53
|
+
run: |
|
|
54
|
+
mkdir -p experiments
|
|
55
|
+
python -m pytest tests/test_docker.py -v --basetemp=experiments/ci
|
|
56
|
+
- name: Retain reports and diagnostics
|
|
57
|
+
if: always()
|
|
58
|
+
uses: actions/upload-artifact@v4
|
|
59
|
+
with:
|
|
60
|
+
name: docker-experiments
|
|
61
|
+
path: |
|
|
62
|
+
experiments/ci/**/*.html
|
|
63
|
+
experiments/ci/**/*.json
|
|
64
|
+
experiments/ci/**/*.jsonl
|
|
65
|
+
experiments/ci/**/*.txt
|
|
66
|
+
experiments/ci/**/*.log
|
|
67
|
+
experiments/ci/**/*.csv
|
|
68
|
+
experiments/ci/**/*.yaml
|
|
69
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
on:
|
|
3
|
+
release:
|
|
4
|
+
types: [published]
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
concurrency:
|
|
8
|
+
group: pypi-${{ github.event.release.tag_name }}
|
|
9
|
+
cancel-in-progress: false
|
|
10
|
+
jobs:
|
|
11
|
+
tests:
|
|
12
|
+
uses: ./.github/workflows/ci.yml
|
|
13
|
+
build:
|
|
14
|
+
needs: tests
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: '3.11'
|
|
21
|
+
- uses: astral-sh/setup-uv@v6
|
|
22
|
+
- run: python -m pip install build twine
|
|
23
|
+
# Build the wheel from the sdist, so both published formats are exercised.
|
|
24
|
+
- run: python -m build
|
|
25
|
+
- run: python -m twine check --strict dist/*
|
|
26
|
+
- run: python -m pip install dist/*.whl
|
|
27
|
+
- name: Match release tag to package version
|
|
28
|
+
env:
|
|
29
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
30
|
+
run: |
|
|
31
|
+
python - <<'PY'
|
|
32
|
+
import os
|
|
33
|
+
from importlib.metadata import version
|
|
34
|
+
expected = 'v' + version('abench')
|
|
35
|
+
if os.environ['RELEASE_TAG'] != expected:
|
|
36
|
+
raise SystemExit(f'Release tag must be {expected}')
|
|
37
|
+
PY
|
|
38
|
+
- name: Smoke test isolated uvx installation
|
|
39
|
+
run: |
|
|
40
|
+
uvx --from "$PWD"/dist/abench-*.whl abench --version
|
|
41
|
+
uvx --from "$PWD"/dist/abench-*.whl abench --help
|
|
42
|
+
- uses: actions/upload-artifact@v4
|
|
43
|
+
with:
|
|
44
|
+
name: python-distributions
|
|
45
|
+
path: dist/*
|
|
46
|
+
if-no-files-found: error
|
|
47
|
+
publish:
|
|
48
|
+
needs: build
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
environment:
|
|
51
|
+
name: pypi
|
|
52
|
+
url: https://pypi.org/p/abench
|
|
53
|
+
permissions:
|
|
54
|
+
id-token: write
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/download-artifact@v4
|
|
57
|
+
with:
|
|
58
|
+
name: python-distributions
|
|
59
|
+
path: dist/
|
|
60
|
+
- name: Publish distributions using Trusted Publishing
|
|
61
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
abench-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, ActivitySim
|
|
4
|
+
Copyright (c) 2024, ActivitySim
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
abench-0.1.0/MANIFEST.in
ADDED
abench-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: abench
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reproducible ActivitySim runtime and memory benchmarks in Linux containers
|
|
5
|
+
License-Expression: BSD-3-Clause
|
|
6
|
+
Project-URL: Homepage, https://github.com/ActivitySim/abench
|
|
7
|
+
Project-URL: Documentation, https://github.com/ActivitySim/abench#readme
|
|
8
|
+
Project-URL: Repository, https://github.com/ActivitySim/abench
|
|
9
|
+
Project-URL: Issues, https://github.com/ActivitySim/abench/issues
|
|
10
|
+
Keywords: activitysim,benchmark,transportation,memory,sharrow
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Operating System :: MacOS
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Topic :: System :: Benchmark
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: PyYAML>=6
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: pytest>=8; extra == "test"
|
|
24
|
+
Requires-Dist: pandas<3; extra == "test"
|
|
25
|
+
Requires-Dist: pyarrow; extra == "test"
|
|
26
|
+
Requires-Dist: numba; extra == "test"
|
|
27
|
+
Requires-Dist: ruff; extra == "test"
|
|
28
|
+
Requires-Dist: build; extra == "test"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# abench
|
|
32
|
+
|
|
33
|
+
Run reproducible ActivitySim runtime and memory experiments in Linux Docker,
|
|
34
|
+
from macOS or Linux. One runner supports MTC, SANDAG ABM3, and other models through
|
|
35
|
+
small YAML profiles. ActivitySim itself does not need to be installed on the host.
|
|
36
|
+
|
|
37
|
+
With [uv](https://docs.astral.sh/uv/), run without managing a Python environment:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
uvx abench --help
|
|
41
|
+
uvx abench experiments.yaml
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For a specific release use `uvx abench@0.1.0 experiments.yaml`; use
|
|
45
|
+
`uvx abench@latest` to refresh to the latest release. Docker and model data must
|
|
46
|
+
still be available locally. macOS and Linux hosts are supported.
|
|
47
|
+
|
|
48
|
+
Alternatively, install with pip:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python -m pip install abench
|
|
52
|
+
abench run --model-dir /path/to/sandag-abm3-example --profile sandag \
|
|
53
|
+
--source activitysim=ActivitySim/activitysim@<full-40-character-SHA> \
|
|
54
|
+
--source sharrow=ActivitySim/sharrow@<full-40-character-SHA> \
|
|
55
|
+
--multiprocess --processes 4 --sharrow --households 28365 \
|
|
56
|
+
--memory 32g --shm-size 8g --output-dir /path/to/experiments/sandag
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Use `--profile mtc` for MTC; both profiles ship with the package. SANDAG defaults
|
|
60
|
+
to its small `benchmarking-data`, **not full-scale skims**. MTC defaults to
|
|
61
|
+
`data_full`. `--data-dir` overrides either. Model directories need not be Git
|
|
62
|
+
repositories; Git revision/status are recorded where available and model files
|
|
63
|
+
are always snapshotted. Existing example scripts and normal configs are untouched.
|
|
64
|
+
|
|
65
|
+
The host needs Python 3.10+, PyYAML (installed with abench), and a Linux Docker
|
|
66
|
+
engine with cgroup v2 and `memory.peak`. Docker Desktop must have enough VM RAM
|
|
67
|
+
for the chosen memory limit plus VM overhead. The default container is Debian
|
|
68
|
+
Bookworm/Python 3.11. Current instrumentation requires ActivitySim's
|
|
69
|
+
`workflow.State` API (1.4-era or newer); arbitrary historical revisions are not
|
|
70
|
+
promised to work. Build/runtime failures retain diagnostics and a failure report.
|
|
71
|
+
|
|
72
|
+
## Named experiment files
|
|
73
|
+
|
|
74
|
+
Write common options once and override only what differs between runs:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
schema_version: 1
|
|
78
|
+
vars:
|
|
79
|
+
households: 28365
|
|
80
|
+
warmup_households: 5000
|
|
81
|
+
model: /path/to/sandag-abm3-example
|
|
82
|
+
output_root: ./results/sandag-${timestamp}
|
|
83
|
+
defaults:
|
|
84
|
+
model_dir: ${model}
|
|
85
|
+
profile: sandag
|
|
86
|
+
data_dir: ${model}/benchmarking-data
|
|
87
|
+
config_overlay: ["${model}/configs_explicit_chunk"]
|
|
88
|
+
multiprocess: true
|
|
89
|
+
processes: 4
|
|
90
|
+
sharrow: true
|
|
91
|
+
households: ${households}
|
|
92
|
+
warmup_households: ${warmup_households}
|
|
93
|
+
memory: 80g
|
|
94
|
+
shm_size: 8g
|
|
95
|
+
sources:
|
|
96
|
+
- sharrow=ActivitySim/sharrow@fc175b27d8e0c5d202721c67d96b050e6117b235
|
|
97
|
+
runs:
|
|
98
|
+
main:
|
|
99
|
+
sources:
|
|
100
|
+
- activitysim=ActivitySim/activitysim@5c6fae24a91a57a2d6dfc2e1dbe062a61d94545a
|
|
101
|
+
pr1110:
|
|
102
|
+
sources:
|
|
103
|
+
- activitysim=ActivitySim/activitysim@51e298a84276813946e1d623c9a5785e078e022f
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Save it as `sandag.yaml`, then run:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
abench sandag.yaml
|
|
110
|
+
# Or check all runs without building images or running models:
|
|
111
|
+
abench validate sandag.yaml
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
A ready-to-use [SANDAG chunked suite](examples/sandag-chunked.yaml) is included
|
|
115
|
+
in the repository. Its paths assume abench and the SANDAG repository are siblings.
|
|
116
|
+
The pinned `main` revision is the one used in the earlier trials, not a moving
|
|
117
|
+
branch reference.
|
|
118
|
+
|
|
119
|
+
- `defaults` accepts CLI options using underscores (`shm_size`, `config_overlay`,
|
|
120
|
+
etc.). Use `multiprocess: false` for serial execution and `sharrow: false` to
|
|
121
|
+
disable Sharrow. `sources` accepts the same strings/mappings as model profiles.
|
|
122
|
+
- `runs` is an ordered mapping of names to overrides. Each run inherits defaults;
|
|
123
|
+
ordinary values and lists are replaced. **Sources merge by normalized package
|
|
124
|
+
name**, so changing ActivitySim does not discard the shared Sharrow pin.
|
|
125
|
+
- `${name}` substitutes a reusable scalar from `vars`; terms can reference other
|
|
126
|
+
terms. A whole-value reference preserves its type, including numbers/booleans.
|
|
127
|
+
Undefined references and cycles are errors. No shell or environment expansion
|
|
128
|
+
is performed. `${timestamp}` is a built-in UTC launch identifier shared by all
|
|
129
|
+
runs, with microseconds to avoid reusing output directories.
|
|
130
|
+
- All explicit paths in the suite are relative to the YAML file, independent of
|
|
131
|
+
the terminal's current directory. This includes overlays and custom profile
|
|
132
|
+
paths. Built-in `mtc`/`sandag` profile names retain their meaning. When omitted,
|
|
133
|
+
`model_dir` defaults to the YAML file's directory; the model profile still
|
|
134
|
+
supplies its usual default data/config paths.
|
|
135
|
+
- The suite owns output locations: `output_root/<run-name>/`. Set `output_root`
|
|
136
|
+
once instead of `output_dir` in each run. Existing roots are rejected.
|
|
137
|
+
- All runs are preflighted before the first starts, then run sequentially in file
|
|
138
|
+
order. Failure stops the suite and retains partial results. The combined report
|
|
139
|
+
is `output_root/comparison.html`; individual runs retain their own reports.
|
|
140
|
+
`experiments.yaml` and `suite.json` record the original file and expanded plan.
|
|
141
|
+
- File invocations do not accept additional CLI overrides. Edit `defaults` or the
|
|
142
|
+
relevant run to keep the file a complete description of the experiment.
|
|
143
|
+
|
|
144
|
+
This experiment file describes **which tests to run**. A model profile such as
|
|
145
|
+
`benchmark.yaml` describes **how to configure a model**, and remains reusable
|
|
146
|
+
across suites.
|
|
147
|
+
|
|
148
|
+
## Run controls
|
|
149
|
+
|
|
150
|
+
- `--single-process` (default), or `--multiprocess --processes N`. The count applies
|
|
151
|
+
to every sliced stage; coordinators are additional processes.
|
|
152
|
+
- `--sharrow` (default) or `--no-sharrow`. Sharrow enabled requires its source pin.
|
|
153
|
+
- `--households N` (default 1,000); zero uses the original full input population.
|
|
154
|
+
abench never replicates households. Positive samples must match realized output.
|
|
155
|
+
- `--config-overlay configs_explicit_chunk` adds config directories in listed
|
|
156
|
+
priority order. Relative overlay paths are relative to the model directory.
|
|
157
|
+
- `--memory 16g`, `--shm-size 8g`, `--interval 0.5`, and optional `--platform`.
|
|
158
|
+
- `--output-dir` must be new. `--label` names an experiment, and `--compare` accepts
|
|
159
|
+
earlier experiment directories. Compatible compiled flows are reused automatically;
|
|
160
|
+
the serial warmup still runs.
|
|
161
|
+
|
|
162
|
+
`abench validate` accepts the same experiment arguments without `--output-dir`.
|
|
163
|
+
It checks the profile, required inputs, CSV population size, source pin syntax,
|
|
164
|
+
and Docker capabilities without building an image or running the model. It does
|
|
165
|
+
not prove Git commit availability, package compatibility, or skim consistency;
|
|
166
|
+
those are checked by the build and model run.
|
|
167
|
+
|
|
168
|
+
## Any dependency from GitHub source
|
|
169
|
+
|
|
170
|
+
Repeat `--source` for any Python distribution, including add-on extensions:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
--source 'my-addon[fast]=ExampleOrg/model-addon@<SHA>#subdirectory=python/addon'
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The left side is the **distribution name** (which can differ from its import
|
|
177
|
+
module). Each source uses an exact full SHA and an `organization/repository` name.
|
|
178
|
+
Extras and a repository subdirectory are optional. Profiles can declare the same
|
|
179
|
+
entries as strings or mappings:
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
sources:
|
|
183
|
+
- name: my-addon
|
|
184
|
+
repository: ExampleOrg/model-addon
|
|
185
|
+
commit: '0123456789abcdef0123456789abcdef01234567'
|
|
186
|
+
extras: [fast]
|
|
187
|
+
subdirectory: python/addon
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
CLI sources override profile sources by normalized distribution name. Duplicate
|
|
191
|
+
CLI entries are errors. `--activitysim-commit` and `--sharrow-commit` remain aliases
|
|
192
|
+
for the official repositories; conflicting alias/source declarations are errors.
|
|
193
|
+
|
|
194
|
+
Inside Docker, abench verifies each checkout's Git object, builds a wheel, checks
|
|
195
|
+
its distribution name, then installs all source wheels together with other
|
|
196
|
+
requirements. It runs `pip check` and verifies installed wheel identities. Exact
|
|
197
|
+
source commits, resolved versions, and the full dependency environment are saved.
|
|
198
|
+
All source dependencies must agree: conflicting requirements fail the build.
|
|
199
|
+
|
|
200
|
+
Use profile `requirements` for additional registry requirements and `constraints`
|
|
201
|
+
for resolver bounds or exact transitive pins. Profiles may select `python_image`
|
|
202
|
+
(a compatible Debian-based image, optionally pinned by digest). The default image
|
|
203
|
+
includes a compiler and HDF5 headers. Packages requiring other system libraries
|
|
204
|
+
can use a prebuilt compatible base image. Private GitHub authentication and custom
|
|
205
|
+
OS provisioning are outside the initial interface.
|
|
206
|
+
|
|
207
|
+
Source pins do not freeze unpinned transitive/build dependencies or base images.
|
|
208
|
+
Retain images and dependency manifests for strict reproduction. Build isolation
|
|
209
|
+
may fetch build requirements; constraints currently govern the final environment,
|
|
210
|
+
not those isolated build environments.
|
|
211
|
+
|
|
212
|
+
## Add another model
|
|
213
|
+
|
|
214
|
+
Create `benchmark.yaml` in its model directory, then use `--model-dir`:
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
schema_version: 1
|
|
218
|
+
name: My regional model
|
|
219
|
+
configs: [configs]
|
|
220
|
+
mp_configs: [configs_mp]
|
|
221
|
+
snapshot: [configs, configs_mp, extensions]
|
|
222
|
+
extensions: [extensions]
|
|
223
|
+
data_dir: data
|
|
224
|
+
required_inputs:
|
|
225
|
+
- [households.csv, households.parquet]
|
|
226
|
+
- persons.csv
|
|
227
|
+
- land_use.csv
|
|
228
|
+
- skims.omx
|
|
229
|
+
settings:
|
|
230
|
+
use_shadow_pricing: false
|
|
231
|
+
rng_base_seed: 0
|
|
232
|
+
input_tables:
|
|
233
|
+
households: {}
|
|
234
|
+
persons: {}
|
|
235
|
+
land_use:
|
|
236
|
+
totals: [TOTPOP, TOTHH, TOTEMP]
|
|
237
|
+
zone_columns: [TAZ]
|
|
238
|
+
output_tables:
|
|
239
|
+
households: {}
|
|
240
|
+
persons: {}
|
|
241
|
+
tours: {}
|
|
242
|
+
trips:
|
|
243
|
+
categories: [trip_mode, primary_purpose]
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Paths in a profile are relative to the model directory (except `data_dir`, which
|
|
247
|
+
may be absolute). `configs` and `mp_configs` are ordered, highest priority first.
|
|
248
|
+
`snapshot` must cover config files, local extension modules, and adapter modules;
|
|
249
|
+
entries must not overlap or contain directory symlinks. Data is mounted read-only
|
|
250
|
+
and should not change during a run. Profiles are trusted model code/configuration.
|
|
251
|
+
|
|
252
|
+
Settings precedence, lowest to highest: **normal model configs → profile settings
|
|
253
|
+
→ user overlays → required CLI controls** (sample, SP/MP, worker counts, Sharrow,
|
|
254
|
+
and fail-fast). Generated inheriting profile configs preserve this ordering when
|
|
255
|
+
ActivitySim reconstructs worker settings. Component overlays remain independent.
|
|
256
|
+
|
|
257
|
+
Optional profile fields:
|
|
258
|
+
|
|
259
|
+
| Field | Purpose |
|
|
260
|
+
|---|---|
|
|
261
|
+
| `models_from`, `exclude_models` | Take a YAML `models` list and explicitly omit diagnostic steps. Otherwise use normal settings. |
|
|
262
|
+
| `mp_settings` | Read `multiprocess_steps` from a separate YAML file. |
|
|
263
|
+
| `extensions` | Import modules through ActivitySim's registration mechanism, including spawned workers. Installing a package alone does not register its components. |
|
|
264
|
+
| `adapter: module:function` | Optional `function(state, spec, phase)` initialization hook, called once in the model parent before execution. Use `state.import_extensions` for worker setup; parent-only mutations are not automatically worker initialization. |
|
|
265
|
+
| `input_tables`, `output_tables` | Logical table names mapped to summary options: `file` (stem), `totals`, `categories`, and `zone_columns` for land use. CSV and Parquet are supported. Use logical `households` for sample validation. |
|
|
266
|
+
| `output_prefix` | Default `final_`; applied to output file stems. |
|
|
267
|
+
| `household_table` | Default `households.csv`, used for early CSV sample validation. Parquet samples are checked after execution. |
|
|
268
|
+
| `zone_label` | Display label for land-use rows, such as zones or MAZs. |
|
|
269
|
+
|
|
270
|
+
For specialized data formats, an adapter can arrange compatible CSV/Parquet
|
|
271
|
+
summary outputs. The initial generic reader does not interpret arbitrary binary
|
|
272
|
+
model outputs.
|
|
273
|
+
|
|
274
|
+
## Measurement and reports
|
|
275
|
+
|
|
276
|
+
Sharrow runs first execute the model in a separate **single-process** warmup,
|
|
277
|
+
using **min(target households, 5000)** households by default. For `--households 0`,
|
|
278
|
+
the target is the full available population, so warmup uses at most 5000 of those
|
|
279
|
+
households. Set `--warmup-households N` (or `warmup_households: N` in experiment
|
|
280
|
+
YAML) to change this positive cap. Warmup always uses one process; measured runs
|
|
281
|
+
retain their requested sample and worker count. Model config directories, seed,
|
|
282
|
+
chunk overlays, and flow cache path are retained from the target experiment.
|
|
283
|
+
|
|
284
|
+
Compiled flows are automatically reused across runs and suites, including changes
|
|
285
|
+
in ActivitySim revisions, sample sizes, process counts, and model configs. The
|
|
286
|
+
persistent host cache defaults to `~/.cache/abench/flows`. Change it with
|
|
287
|
+
`--flow-cache-dir PATH` (`flow_cache_dir` in YAML), or disable automatic reads and
|
|
288
|
+
writes with `--no-reuse-flows` (`reuse_flows: false`). `--cache-from` remains an
|
|
289
|
+
explicit seed option with its existing stricter dependency checks.
|
|
290
|
+
|
|
291
|
+
Compatibility uses the **installed** Sharrow, Numba, llvmlite, and NumPy versions,
|
|
292
|
+
plus their source repository/commit identities when applicable, Python version,
|
|
293
|
+
and container architecture/CPU features. ActivitySim and model settings are
|
|
294
|
+
excluded from this key: Sharrow identifies generated flows by their contents,
|
|
295
|
+
and Numba checks cached signatures. Changed flows can compile during warmup.
|
|
296
|
+
An existing cache does **not** guarantee that warmup will need no compilation.
|
|
297
|
+
|
|
298
|
+
Each experiment receives a private copy with source timestamps preserved. Warmup
|
|
299
|
+
always runs, and successful warmups atomically update the persistent cache before
|
|
300
|
+
measurement starts. Compatible simultaneous experiments wait for each other to avoid losing
|
|
301
|
+
compiled signatures when attempts update Numba cache indexes. Only `cache/flows`
|
|
302
|
+
is shared, never model data, outputs, or shared-memory artifacts. Cache identity
|
|
303
|
+
and reuse counts are recorded in `flow-cache-identity.json` and `experiment.json`.
|
|
304
|
+
The persistent cache can be deleted between runs to reclaim disk space; older
|
|
305
|
+
experiments created before this feature are not automatically imported.
|
|
306
|
+
|
|
307
|
+
A smaller serial warmup may not exercise every flow/type signature needed by the
|
|
308
|
+
measured run. Each measured attempt therefore records flow compilation and allows
|
|
309
|
+
it to finish. If compilation occurred, the completed attempt becomes **cache
|
|
310
|
+
preparation**, and none of its runtime or memory results qualify as benchmark
|
|
311
|
+
results. Its diagnostics and outputs are retained under `attempts/attempt-001`,
|
|
312
|
+
`attempts/attempt-002`, etc. Newly compiled flows are published to the shared cache.
|
|
313
|
+
|
|
314
|
+
The model then restarts in a fresh container with fresh outputs and model caches,
|
|
315
|
+
using the same settings and expanded flow cache. Only an attempt with **zero flow
|
|
316
|
+
compilations** is accepted. All attempts keep permanent directories under
|
|
317
|
+
`attempts/`; `measured/` links to the accepted attempt. By default abench allows
|
|
318
|
+
**two additional attempts** (three total). Set `--cache-retries N` or
|
|
319
|
+
`cache_retries: N` in YAML; zero allows no retries. If compilation persists, the
|
|
320
|
+
experiment fails with the final attempt's diagnostics retained. Ordinary model
|
|
321
|
+
errors, OOMs, and output validation failures stop immediately and are never
|
|
322
|
+
retried as cache preparation.
|
|
323
|
+
|
|
324
|
+
The report and `experiment.json` include attempt history. Each attempt retains
|
|
325
|
+
`cache-miss-details-*.jsonl`, its settings, component timings, and memory samples.
|
|
326
|
+
Ordinary non-flow compilation and disk-cache loading remain included in accepted
|
|
327
|
+
measurements. Flow tracking uses private Numba internals and is covered by real
|
|
328
|
+
compilation, cache-hit, and Docker retry tests.
|
|
329
|
+
|
|
330
|
+
Memory is the whole-container cgroup v2 charge, counting shared pages once.
|
|
331
|
+
Blue is `memory.current` (including file cache, shared memory, and kernel costs).
|
|
332
|
+
Green dashed is `anon + shmem`, a subset excluding ordinary file cache and kernel
|
|
333
|
+
costs. Never add the lines. Swap is recorded separately and disabled by equal
|
|
334
|
+
memory/memory+swap limits. `/dev/shm` capacity is within that limit.
|
|
335
|
+
|
|
336
|
+
Component runtimes show worker mean, population SD, count, and maximum. Worker SD
|
|
337
|
+
is imbalance, not confidence across repeated trials. The component dropdown
|
|
338
|
+
highlights each worker's actual window; overlaps darken and gaps remain clear.
|
|
339
|
+
Overall elapsed includes startup, coordination, and checkpoint writes between
|
|
340
|
+
components. Kernel peak includes startup; warmup and post-run summaries are
|
|
341
|
+
excluded. Shared VM page-cache ownership can influence container charges: this
|
|
342
|
+
is not a cold-input I/O benchmark.
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
abench report --compare /path/to/run-a /path/to/run-b \
|
|
346
|
+
--output-dir /path/to/comparison.html
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Reports are offline HTML/SVG/JavaScript plus normalized JSON. They retain fastest
|
|
350
|
+
successful component highlighting and use common memory axes. Existing MTC and
|
|
351
|
+
SANDAG schema-1 experiments remain readable, including approximate legacy timing
|
|
352
|
+
windows where only completion logs exist. New experiments use schema 2 and include
|
|
353
|
+
source manifests, resolved profile/settings, model and harness snapshots, file
|
|
354
|
+
hashes, Docker details, and source installation provenance. Input file size/mtime
|
|
355
|
+
records are provenance hints, not content hashes of large skims.
|
|
356
|
+
|
|
357
|
+
## Development and CI
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
python -m pip install -e '.[test]' -r tests/requirements.txt
|
|
361
|
+
python -m pytest -m 'not docker'
|
|
362
|
+
pre-commit run --all-files
|
|
363
|
+
python -m build
|
|
364
|
+
ABENCH_DOCKER_TESTS=1 python -m pytest tests/test_docker.py -v
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Install Node.js to exercise the offline chart selector test. GitHub Actions runs
|
|
368
|
+
unit tests on Python 3.10–3.12, lint/format checks, wheel packaging checks, and Linux
|
|
369
|
+
Docker integration. The Docker tests build pinned ActivitySim/Sharrow sources and
|
|
370
|
+
run a four-household extension workflow in serial and multiprocess modes, checking
|
|
371
|
+
warmup, generated-code cache reuse, per-worker timings, merged outputs, memory,
|
|
372
|
+
and reports. They do not require either example repository or large datasets.
|
|
373
|
+
|
|
374
|
+
Adapted from the MTC and SANDAG benchmark harnesses developed in this workspace.
|
|
375
|
+
The original measurement approach was informed by WSP's Lighthouse production
|
|
376
|
+
benchmark. See LICENSE for the retained BSD license.
|
|
377
|
+
|
|
378
|
+
## Releases
|
|
379
|
+
|
|
380
|
+
See [RELEASING.md](https://github.com/ActivitySim/abench/blob/main/RELEASING.md)
|
|
381
|
+
for Trusted Publishing setup and release instructions.
|