Repository navigation
Commit ff35ee4
authored
fix(stamping): skip build data spawn when --stamp=false (bazel-contrib#4160)
## Summary
`PyWriteBuildData` is dirty on every build with a cold Skyframe when
outputs are not downloaded. That is, once per `py_binary` and `py_test`
in the build. When stamping is off, the output is a constant, so the
action spawn is pure overhead.
## Root Cause Analysis
The output is declared with
`_py_builtins.declare_constant_metadata_file`. Constant metadata always
reports itself as unchanged, so Bazel cannot validate it from the action
cache. It stats the output on disk instead.
Under `--remote_download_outputs=minimal` the output is not on disk. The
stat fails and the action is dirty. It re-executes, hits the remote
cache, is still not downloaded, and is dirty again on the next
cold-server build. Setting `--remote_download_regex` to match the file
avoids this, at the cost of downloading it, which confirms the stat is
the trigger.
The use of a constant metadata file is justified (as per the comment in
the code). With stamping on, the action reads `volatile-status.txt`,
which changes every build. The build data file is in the binary's
runfiles, so without it its consumers would invalidate on every build
due to timestamps.
However, with stamping off, there is no volatile input. There is nothing
to shield. Unfortunately, the current implementation keeps the
_additional_ cost (constant metadata being always unchanged plus failed
`stat` syscalls) for none of the benefits.
## Change
When `is_stamping_enabled(ctx)` is false, the content of the file is
known at analysis time:
```
TARGET <label>
STAMPED FALSE
```
So declare an ordinary output and write it with `ctx.actions.write`. No
spawn, and no constant metadata output.
Note this is broader than `--nostamp`. `is_stamping_enabled` is also
false for the exec configuration and for `stamp = 0`, so tool-config
binaries benefit from the fix even when `--stamp=true` is set at the top
level.
The stamped path is unchanged and keeps its constant metadata output.
## Compatibility
The output is byte-identical. The label is written with `str(ctx.label)`
to match `"TARGET": str(ctx.label)` in the spawn's env, which yields the
canonical `@@//pkg:target` form. `ctx.actions.args().add(ctx.label)`
renders the display form and drops the `@@`.
After the change, the tests in `tests/build_data/build_data_test.py`
pass without any modifications.
## Alternative considered
Keeping the spawn and declaring an ordinary output would also fix the
dirtiness. Writing at analysis time is lighter, since it needs no
subprocess.
## Environment
rules_python 2.2.0, Bazel 9.2.0, Linux. Reproduce with
`--remote_download_outputs=minimal` against a warm remote cache, then
`bazel shutdown` and rebuild.1 parent 809c0f5 commit ff35ee4
2 files changed
Lines changed: 36 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1634 | 1634 | | |
1635 | 1635 | | |
1636 | 1636 | | |
| 1637 | + | |
| 1638 | + | |
| 1639 | + | |
| 1640 | + | |
| 1641 | + | |
| 1642 | + | |
| 1643 | + | |
| 1644 | + | |
| 1645 | + | |
| 1646 | + | |
| 1647 | + | |
| 1648 | + | |
| 1649 | + | |
| 1650 | + | |
| 1651 | + | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
| 1657 | + | |
| 1658 | + | |
1637 | 1659 | | |
1638 | | - | |
1639 | | - | |
1640 | | - | |
1641 | | - | |
1642 | | - | |
1643 | | - | |
1644 | | - | |
1645 | | - | |
1646 | | - | |
1647 | | - | |
| 1660 | + | |
| 1661 | + | |
1648 | 1662 | | |
1649 | 1663 | | |
1650 | 1664 | | |
| |||
1670 | 1684 | | |
1671 | 1685 | | |
1672 | 1686 | | |
| 1687 | + | |
| 1688 | + | |
| 1689 | + | |
| 1690 | + | |
| 1691 | + | |
| 1692 | + | |
1673 | 1693 | | |
1674 | 1694 | | |
1675 | | - | |
| 1695 | + | |
1676 | 1696 | | |
1677 | 1697 | | |
1678 | 1698 | | |
| |||
1698 | 1718 | | |
1699 | 1719 | | |
1700 | 1720 | | |
1701 | | - | |
| 1721 | + | |
1702 | 1722 | | |
1703 | 1723 | | |
1704 | 1724 | | |
1705 | | - | |
| 1725 | + | |
1706 | 1726 | | |
1707 | | - | |
| 1727 | + | |
1708 | 1728 | | |
1709 | 1729 | | |
1710 | 1730 | | |
| |||
0 commit comments