Don’t call spec.format in Database._get_matching_spec_key (#38792)

`"%s" % spec` formats the spec with deps included, which produces sometimes KBs
of data and is slow to run in pure Python. It can delay otherwise very short-lived
read/write locks on the database.

Discovered in #38762 where profile output showed about 2 seconds is spent in
`spec.format`, which is significant overhead when using multiprocessing to install
from binary cache in parallel (installation often takes <5s for small packages). With
this change, `spec.format` no longer shows up in profile output.

(This line hasn't changed since Spack v0.9 ;p)

* move format() call to custom NoSuchSpecError exception
* add a comment saying why, so we can eventually change `Spec.__str__`
This commit is contained in:
Harmen Stoppels 2023-07-09 17:27:38 +02:00 committed by GitHub
parent 3c14569b8e
commit 374fda1063
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1216,7 +1216,7 @@ def _get_matching_spec_key(self, spec, **kwargs):
match = self.query_one(spec, **kwargs)
if match:
return match.dag_hash()
raise KeyError("No such spec in database! %s" % spec)
raise NoSuchSpecError(spec)
return key
@_autospec
@ -1672,3 +1672,17 @@ def __init__(self, database, expected, found):
@property
def database_version_message(self):
return f"The expected DB version is '{self.expected}', but '{self.found}' was found."
class NoSuchSpecError(KeyError):
"""Raised when a spec is not found in the database."""
def __init__(self, spec):
self.spec = spec
super().__init__(spec)
def __str__(self):
# This exception is raised frequently, and almost always
# caught, so ensure we don't pay the cost of Spec.__str__
# unless the exception is actually printed.
return f"No such spec in database: {self.spec}"