![]() This PR tweaks the representation of `Tags` in order to offer a faster implementation of `WheelFilename::is_compatible`. We now use a nested map of tags that lets us avoid looping over every supported platform tag. As the code comments suggest, that is the essential gain. We still do not mind looping over the tags in each wheel name since they tend to be quite small. And pushing our thumb on that side of things can make things worse overall since it would likely slow down WheelFilename construction itself. For micro-benchmarks, we improve considerably for compatibility checking: $ critcmp base test3 group base test3 ----- ---- ----- build_platform_tags/burntsushi-archlinux 1.00 46.2±0.28µs ? ?/sec 2.48 114.8±0.45µs ? ?/sec wheelname_parsing/flyte-long-compatible 1.00 624.8±3.31ns 174.0 MB/sec 1.01 629.4±4.30ns 172.7 MB/sec wheelname_parsing/flyte-long-incompatible 1.00 743.6±4.23ns 165.4 MB/sec 1.00 746.9±4.62ns 164.7 MB/sec wheelname_parsing/flyte-short-compatible 1.00 526.7±4.76ns 54.3 MB/sec 1.01 530.2±5.81ns 54.0 MB/sec wheelname_parsing/flyte-short-incompatible 1.00 540.4±4.93ns 60.0 MB/sec 1.01 545.7±5.31ns 59.4 MB/sec wheelname_parsing_failure/flyte-long-extension 1.00 13.6±0.13ns 3.2 GB/sec 1.01 13.7±0.14ns 3.2 GB/sec wheelname_parsing_failure/flyte-short-extension 1.00 14.0±0.20ns 1160.4 MB/sec 1.01 14.1±0.14ns 1146.5 MB/sec wheelname_tag_compatibility/flyte-long-compatible 11.33 159.8±2.79ns 680.5 MB/sec 1.00 14.1±0.23ns 7.5 GB/sec wheelname_tag_compatibility/flyte-long-incompatible 237.60 1671.8±37.99ns 73.6 MB/sec 1.00 7.0±0.08ns 17.1 GB/sec wheelname_tag_compatibility/flyte-short-compatible 16.07 223.5±8.60ns 128.0 MB/sec 1.00 13.9±0.30ns 2.0 GB/sec wheelname_tag_compatibility/flyte-short-incompatible 149.83 628.3±2.13ns 51.6 MB/sec 1.00 4.2±0.10ns 7.6 GB/sec We do regress slightly on the time it takes for `Tags::new` to run, but this is somewhat expected. And in absolute terms, 114us is perfectly acceptable given that it's only executed ~once for each `puffin` invocation. Ad hoc benchmarks indicate an overall 25% perf improvement in `puffin pip-compile` times. This roughly corresponds with how much time `is_compatible` was taking. Indeed, profiling confirms that it has virtually disappeared from the profile. Fixes #157 |
||
---|---|---|
.cargo | ||
.github/workflows | ||
crates | ||
scripts | ||
vendor/pubgrub | ||
workers/pypi-metadata | ||
.dockerignore | ||
.gitignore | ||
builder.dockerfile | ||
Cargo.lock | ||
Cargo.toml | ||
CONTRIBUTING.md | ||
LICENSE-APACHE | ||
LICENSE-MIT | ||
README.md | ||
ruff.toml | ||
rust-toolchain.toml |
puffin
An experimental Python packaging tool.
Motivation
Puffin is an extremely fast (experimental) Python package resolver and installer, intended to
replace pip
and pip-tools
(pip-compile
and pip-sync
).
Puffin itself is not a complete "package manager", but rather a tool for locking dependencies
(similar to pip-compile
) and installing them (similar to pip-sync
). Puffin can be used to
generate a set of locked dependencies from a requirements.txt
file, and then install those
locked dependencies into a virtual environment.
Puffin represents an intermediary goal in our pursuit of building a "Cargo for Python": a Python
package manager that is extremely fast, reliable, and easy to use -- capable of replacing not only
pip
, but also pipx
, pip-tools
, virtualenv
, tox
, setuptools
, and even pyenv
, by way of
managing the Python installation itself.
Puffin's limited scope allows us to solve many of the low-level problems that are required to
build such a package manager (like package installation) while shipping an immediately useful tool
with a minimal barrier to adoption. Try it today in lieu of pip
and pip-tools
.
Features
- Extremely fast dependency resolution and installation: install dependencies in sub-second time.
- Disk-space efficient: Puffin uses a global cache to deduplicate dependencies, and uses Copy-on-Write on supported filesystems to reduce disk usage.
Limitations
Puffin does not yet support:
- Windows
- ...
Like pip-compile
, Puffin generates a platform-specific requirements.txt
file (unlike, e.g.,
poetry
, which generates a platform-agnostic poetry.lock
file). As such, Puffin's
requirements.txt
files are not portable across platforms and Python versions.
Usage
To resolve a requirements.in
file:
cargo run -p puffin-cli -- pip-compile requirements.in
To install from a resolved requirements.txt
file:
cargo run -p puffin-cli -- pip-sync requirements.txt
For more, see cargo run -p puffin-cli -- --help
:
Usage: puffin [OPTIONS] <COMMAND>
Commands:
pip-compile Compile a `requirements.in` file to a `requirements.txt` file
pip-sync Sync dependencies from a `requirements.txt` file
pip-uninstall Uninstall packages from the current environment
clean Clear the cache
freeze Enumerate the installed packages in the current environment
venv Create a virtual environment
add Add a dependency to the workspace
remove Remove a dependency from the workspace
help Print this message or the help of the given subcommand(s)
Options:
-q, --quiet Do not print any output
-v, --verbose Use verbose output
-n, --no-cache Avoid reading from or writing to the cache
--cache-dir <CACHE_DIR> Path to the cache directory [env: PUFFIN_CACHE_DIR=]
-h, --help Print help
-V, --version Print version
License
Puffin is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in Puffin by you, as defined in the Apache-2.0 license, shall be dually licensed as above, without any additional terms or conditions.