Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolution stress test (>10 seconds offline with warm cache) #10438

Open
notatallshaw opened this issue Jan 9, 2025 · 2 comments
Open

Resolution stress test (>10 seconds offline with warm cache) #10438

notatallshaw opened this issue Jan 9, 2025 · 2 comments
Assignees
Labels
great writeup A wonderful example of a quality contribution 💜 performance Potential performance improvement

Comments

@notatallshaw
Copy link
Collaborator

First, I don't use these requirements anymore, they are based on requirements I used to use ~6 months ago, so this is not a priority for me, but I do use these as a smoke test for uv. These are reduced from the real requirements, which were built to match the Airflow dockerfile, the Python 3.10 Airflow constraints file, and other production and development requirements.

Secondly, there is a big performance difference between my work environment and my home environment I haven't been able to explain, in my home environment I am only able to produce slow performance with fork strategy Requires-Python and python version 3.8, but in my work environment I am able to produce slow performance with both fork strategies and python version 3.10, and in my work environment I see a 20+% slow down between 0.5.15 and 0.5.16 but in my home environment I see almost no difference. I am trying to identify anything other than hardware that might be the difference.

See requirements.in and constraints.txt:

requirements.in

apache-airflow[amazon,async,google,google_auth,grpc,hashicorp,http,ldap,mysql,odbc,pandas,postgres,redis,sftp,slack,ssh,statsd,virtualenv]==2.3.4
alembic>=1.8.1
ipython>=8.4.0

constraints.txt

adal==1.2.7
alembic==1.8.1
amqp==5.1.1
anyio==3.6.1
apache-airflow==2.3.4
apache-airflow-providers-amazon==5.0.0
apache-airflow-providers-celery==3.0.0
apache-airflow-providers-cncf-kubernetes==4.3.0
apache-airflow-providers-common-sql==1.1.0
apache-airflow-providers-docker==3.1.0
apache-airflow-providers-elasticsearch==4.2.0
apache-airflow-providers-ftp==3.1.0
apache-airflow-providers-google==8.3.0
apache-airflow-providers-grpc==3.0.0
apache-airflow-providers-hashicorp==3.1.0
apache-airflow-providers-http==4.0.0
apache-airflow-providers-imap==3.0.0
apache-airflow-providers-microsoft-azure==4.2.0
apache-airflow-providers-mysql==3.2.0
apache-airflow-providers-odbc==3.1.1
apache-airflow-providers-postgres==5.2.0
apache-airflow-providers-redis==3.0.0
apache-airflow-providers-sendgrid==3.0.0
apache-airflow-providers-sftp==4.0.0
apache-airflow-providers-slack==5.1.0
apache-airflow-providers-sqlite==3.2.0
apache-airflow-providers-ssh==3.1.0
apispec==3.3.2
argcomplete==2.0.0
asn1crypto==1.5.1
attrs==22.1.0
Authlib==0.15.5
azure-batch==12.0.0
azure-common==1.1.28
azure-core==1.25.0
azure-cosmos==4.3.0
azure-datalake-store==0.0.52
azure-identity==1.10.0
azure-keyvault-secrets==4.5.1
azure-kusto-data==0.0.45
azure-mgmt-containerinstance==1.5.0
azure-mgmt-core==1.3.2
azure-mgmt-datafactory==1.1.0
azure-mgmt-datalake-nspkg==3.0.1
azure-mgmt-datalake-store==0.5.0
azure-mgmt-nspkg==3.0.2
azure-mgmt-resource==21.1.0
azure-nspkg==3.0.2
azure-servicebus==7.8.0
azure-storage-blob==12.8.1
azure-storage-common==2.1.0
azure-storage-file==2.1.0
Babel==2.10.3
bcrypt==3.2.2
beautifulsoup4==4.11.1
billiard==3.6.4.0
blinker==1.5
boto3==1.24.56
botocore==1.27.56
cachelib==0.9.0
cachetools==4.2.2
cattrs==22.1.0
celery==5.2.7
certifi==2022.6.15
cffi==1.15.1
charset-normalizer==2.0.12
click==8.1.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
clickclick==20.10.2
cloudpickle==2.1.0
colorama==0.4.5
colorlog==4.8.0
commonmark==0.9.1
connexion==2.14.0
cron_descriptor==1.2.31
croniter==1.3.5
cryptography==36.0.2
dask==2022.8.0
db-dtypes==1.0.3
decorator==5.1.1
Deprecated==1.2.13
dill==0.3.1.1
distlib==0.3.5
distributed==2022.8.0
dnspython==2.2.1
docker==6.1.3
docutils==0.19
elasticsearch==7.13.4
elasticsearch-dbapi==0.2.9
elasticsearch-dsl==7.4.0
email-validator==1.2.1
eventlet==0.33.1
exceptiongroup==1.0.0rc8
filelock==3.8.0
Flask==2.2.2
Flask-AppBuilder==4.1.3
Flask-Babel==2.0.0
Flask-Caching==2.0.1
Flask-JWT-Extended==4.4.4
Flask-Login==0.6.2
Flask-Session==0.4.0
Flask-SQLAlchemy==2.5.1
Flask-WTF==0.15.1
flower==1.2.0
fsspec==2022.7.1
future==0.18.2
gevent==21.12.0
google-ads==18.0.0
google-api-core==2.8.2
google-api-python-client==1.12.11
google-auth==2.10.0
google-auth-httplib2==0.1.0
google-auth-oauthlib==0.5.2
google-cloud-aiplatform==1.16.1
google-cloud-appengine-logging==1.1.3
google-cloud-audit-log==0.2.4
google-cloud-automl==2.8.0
google-cloud-bigquery==2.34.4
google-cloud-bigquery-datatransfer==3.7.0
google-cloud-bigquery-storage==2.14.1
google-cloud-bigtable==1.7.2
google-cloud-build==3.9.0
google-cloud-container==2.11.1
google-cloud-core==2.3.2
google-cloud-datacatalog==3.9.0
google-cloud-dataform==0.2.0
google-cloud-dataplex==1.1.0
google-cloud-dataproc==5.0.0
google-cloud-dataproc-metastore==1.6.0
google-cloud-dlp==1.0.2
google-cloud-kms==2.12.0
google-cloud-language==1.3.2
google-cloud-logging==3.2.1
google-cloud-memcache==1.4.1
google-cloud-monitoring==2.11.0
google-cloud-orchestration-airflow==1.4.1
google-cloud-os-login==2.7.1
google-cloud-pubsub==2.13.5
google-cloud-redis==2.9.0
google-cloud-resource-manager==1.6.0
google-cloud-secret-manager==1.0.2
google-cloud-spanner==1.19.3
google-cloud-speech==1.3.4
google-cloud-storage==1.44.0
google-cloud-tasks==2.10.1
google-cloud-texttospeech==1.0.3
google-cloud-translate==1.7.2
google-cloud-videointelligence==1.16.3
google-cloud-vision==1.0.2
google-cloud-workflows==1.7.1
google-crc32c==1.3.0
google-resumable-media==2.3.3
googleapis-common-protos==1.56.4
graphviz==0.20.1
greenlet==1.1.2
grpc-google-iam-v1==0.12.4
grpcio==1.47.0
grpcio-gcp==0.2.2
grpcio-status==1.47.0
gunicorn==20.1.0
h11==0.12.0
HeapDict==1.0.1
httpcore==0.15.0
httplib2==0.20.4
httpx==0.23.0
humanize==4.3.0
hvac==1.1.1
idna==3.3
inflection==0.5.1
isodate==0.6.1
itsdangerous==2.1.2
Jinja2==3.1.2
jmespath==0.10.0
json-merge-patch==0.2
jsonpath-ng==1.5.3
jsonschema==4.13.0
kombu==5.2.4
kubernetes==23.6.0
lazy-object-proxy==1.7.1
ldap3==2.9.1
linkify-it-py==2.0.0
locket==1.0.0
lockfile==0.12.2
looker-sdk==22.10.0
lxml==4.9.1
Mako==1.2.1
Markdown==3.4.1
markdown-it-py==2.1.0
MarkupSafe==2.1.1
marshmallow==3.17.0
marshmallow-enum==1.5.1
marshmallow-oneofschema==3.0.1
marshmallow-sqlalchemy==0.26.1
mdit-py-plugins==0.3.0
mdurl==0.1.2
msal==1.18.0
msal-extensions==1.0.0
msgpack==1.0.4
msrest==0.7.1
msrestazure==0.6.4
mypy-boto3-appflow==1.24.36.post1
mypy-boto3-rds==1.24.54
mypy-boto3-redshift-data==1.24.36.post1
mysql-connector-python==8.0.30
mysqlclient==2.1.1
numpy==1.22.4
oauthlib==3.2.0
packaging==21.3
pandas==1.4.3
pandas-gbq==0.17.8
paramiko==2.11.0
partd==1.3.0
pathspec==0.9.0
pendulum==2.1.2
platformdirs==2.5.2
pluggy==1.0.0
ply==3.11
portalocker==2.5.1
prison==0.2.1
prometheus-client==0.14.1
prompt-toolkit==3.0.30
proto-plus==1.19.6
protobuf==3.20.0
psutil==5.9.1
psycopg2-binary==2.9.3
pyarrow==6.0.1
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.21
pydata-google-auth==1.4.0
Pygments==2.13.0
PyJWT==2.4.0
PyNaCl==1.5.0
pyodbc==4.0.34
pyOpenSSL==22.0.0
pyparsing==3.0.9
pyrsistent==0.18.1
python-daemon==2.3.1
python-dateutil==2.8.2
python-http-client==3.3.7
python-ldap==3.4.2
python-nvd3==0.15.0
python-slugify==6.1.2
pytz==2022.1
pytzdata==2020.1
PyYAML==6.0
redis==3.5.3
redshift-connector==2.0.908
requests==2.28.0
requests-oauthlib==1.3.1
requests-toolbelt==0.9.1
rfc3986==1.5.0
rich==12.5.1
rsa==4.9
s3transfer==0.6.0
scramp==1.4.1
sendgrid==6.9.7
setproctitle==1.3.2
six==1.16.0
slack-sdk==3.18.1
sniffio==1.2.0
sortedcontainers==2.4.0
soupsieve==2.3.2.post1
SQLAlchemy==1.4.27
sqlalchemy-bigquery==1.4.4
SQLAlchemy-JSONField==1.0.0
sqlalchemy-redshift==0.8.11
SQLAlchemy-Utils==0.38.3
sqlparse==0.4.2
sshtunnel==0.4.0
starkbank-ecdsa==2.0.3
statsd==3.3.0
swagger-ui-bundle==0.0.9
tabulate==0.8.10
tblib==1.7.0
tenacity==8.0.1
termcolor==1.1.0
text-unidecode==1.3
toolz==0.12.0
tornado==6.1
typing_extensions==4.3.0
uamqp==1.6.0
uc-micro-py==1.0.1
unicodecsv==0.14.1
uritemplate==3.0.1
urllib3==1.26.11
vine==5.0.0
virtualenv==20.16.3
watchtower==2.0.1
wcwidth==0.2.5
websocket-client==1.3.3
Werkzeug==2.2.2
wrapt==1.14.1
WTForms==2.3.3
zict==2.2.0
zope.event==4.5.0
zope.interface==5.4.0

Run Tests:

  1. uv pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 > /dev/null
  2. uv pip compile requirements.in -c constraints.txt --universal --no-progress --python-version 3.8 --offline > /dev/null

On my home machine the second command takes ~13 seconds, on my work machine this takes ~123 seconds.

@konstin konstin added performance Potential performance improvement great writeup A wonderful example of a quality contribution 💜 labels Jan 9, 2025
@konstin
Copy link
Member

konstin commented Jan 9, 2025

Thank you the perfect reproducer! From the profile this is the same underlying problem as #10430: It's 87% in without_extras, a function that's not expected to have a lot of load:

// In the branches, we "sort" the preferences by marker-matching through an iterator that
// first has the matching half and then the mismatching half.
let preferences_match = preferences
.get(package_name)
.filter(|(marker, _index, _version)| env.included_by_marker(marker.pep508()));
let preferences_mismatch = preferences
.get(package_name)
.filter(|(marker, _index, _version)| !env.included_by_marker(marker.pep508()));

Image

Crudely patching that out and applying [https://github.com//pull/10439], the bottleneck is still the same code snippet from above:

Image

@charliermarsh
Copy link
Member

That's good news since this is CPU work which we can always improve :)

konstin added a commit that referenced this issue Jan 9, 2025
Motivated by #10438. Ideally we wouldn't be calling this code that much in the first place, but it's the more idiomatic way to write this code.

Crude-ish benchmark based on #10438 with the `without_markers` patched out:

```
hyperfine --warmup 1 "./uv-1 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8" "./uv-2 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8"
Benchmark 1: ./uv-1 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8
  Time (mean ± σ):      1.229 s ±  0.018 s    [User: 1.206 s, System: 0.111 s]
  Range (min … max):    1.211 s …  1.269 s    10 runs

Benchmark 2: ./uv-2 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8
  Time (mean ± σ):     873.8 ms ±   5.1 ms    [User: 851.2 ms, System: 112.5 ms]
  Range (min … max):   865.2 ms … 880.4 ms    10 runs

Summary
  ./uv-2 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8 ran
    1.41 ± 0.02 times faster than ./uv-1 pip compile scripts/requirements/airflow2-req.in -c scripts/requirements/airflow2-constraints.txt --universal --python-version 3.8
```
@BurntSushi BurntSushi self-assigned this Jan 9, 2025
konstin added a commit that referenced this issue Jan 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
great writeup A wonderful example of a quality contribution 💜 performance Potential performance improvement
Projects
None yet
Development

No branches or pull requests

4 participants