Skip to content

Commit 1240e68

Browse files
committed
Don't uselessly recombine registries each time we recurse into subschemas.
Also add a benchmark via @robherring to ensure we compare these timings (validating with or without a registry which isn't really being used). Fixes a ~4-5x slowdown. These are now on par with each other. Closes: #1088
1 parent b62bcfb commit 1240e68

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""
2+
An unused schema registry should not cause slower validation.
3+
4+
"Unused" here means one where no reference resolution is occurring anyhow.
5+
6+
See https://github.com/python-jsonschema/jsonschema/issues/1088.
7+
"""
8+
from pyperf import Runner
9+
from referencing import Registry
10+
from referencing.jsonschema import DRAFT201909
11+
12+
from jsonschema import Draft201909Validator
13+
14+
registry = Registry().with_resource(
15+
"urn:example:foo",
16+
DRAFT201909.create_resource({})
17+
)
18+
19+
schema = {"$ref": "https://json-schema.org/draft/2019-09/schema"}
20+
instance = {"maxLength": 4}
21+
22+
no_registry = Draft201909Validator(schema)
23+
with_useless_registry = Draft201909Validator(schema, registry=registry)
24+
25+
if __name__ == "__main__":
26+
runner = Runner()
27+
28+
runner.bench_func(
29+
"no registry",
30+
lambda: no_registry.is_valid(instance),
31+
)
32+
runner.bench_func(
33+
"useless registry",
34+
lambda: with_useless_registry.is_valid(instance),
35+
)

jsonschema/validators.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,7 @@ class Validator:
224224
format_checker: _format.FormatChecker | None = field(default=None)
225225
# TODO: include new meta-schemas added at runtime
226226
_registry: referencing.jsonschema.SchemaRegistry = field(
227-
default=_DEFAULT_REGISTRY,
228-
converter=lambda value: (
229-
_DEFAULT_REGISTRY
230-
if value is _DEFAULT_REGISTRY
231-
else SPECIFICATIONS.combine(value)
232-
),
227+
default=referencing.Registry(),
233228
kw_only=True,
234229
repr=False,
235230
)
@@ -274,9 +269,9 @@ def evolve(self, **changes):
274269

275270
def __attrs_post_init__(self):
276271
if self._resolver is None:
277-
self._resolver = self._registry.resolver_with_root(
278-
resource=specification.create_resource(self.schema),
279-
)
272+
registry = _DEFAULT_REGISTRY.combine(self._registry)
273+
resource = specification.create_resource(self.schema)
274+
self._resolver = registry.resolver_with_root(resource)
280275

281276
@classmethod
282277
def check_schema(cls, schema, format_checker=_UNSET):

0 commit comments

Comments
 (0)