<#3494 :zap: Speed up function `_jsonschema_type_c...
# meltano-repo-activity
g
#3494 :zap: Speed up function `_jsonschema_type_check` by 164% Pull request opened by codeflash-ai[bot] on <!date^1771369890^{date_short}|2026-02-17T23:11:30Z> 📄 164% (1.64x) speedup for
jsonschematypecheck
in
singersdk/typing.py
⏱️ Runtime :
1.12 milliseconds
→
425 microseconds
(best of
248
runs) 📝 Explanation and details This optimization achieves a 164% speedup (from 1.12ms to 425μs) by replacing recursive function calls with an iterative stack-based approach. Key Performance Improvement: The original code uses recursion with a generator expression (
any(...)
) to traverse nested
anyOf
structures. Each recursive call incurs overhead from: • Function call stack frames • Generator object creation and iteration • Multiple dictionary lookups for
anyOf
keys The optimized version replaces this with an explicit stack and a
while
loop that processes schemas iteratively. This eliminates all recursion overhead and generator costs. Why This is Significantly Faster: 1. Recursion elimination: Line profiler shows the original spends 45.1% of time in the
any()
call and 10.6% in the generator comprehension. The optimized version removes this entirely. 2. Better for deep/wide structures: Test results show dramatic improvements for complex schemas: • Deep nesting (100 levels): 355% faster (25.0μs → 5.50μs) • Wide anyOf (1000 items): 2039% faster (215μs → 10.1μs) • Large non-matching anyOf: 95% faster (213μs → 109μs) 3. Consistent wins on nested structures: Most tests with
anyOf
show 35-150% speedup, while simple type checks see small regressions (11-30% slower) due to stack initialization overhead on trivial inputs. Impact Based on Usage Context: Looking at
function_references
, this function is called multiple times in
to_sql_type()
for each schema conversion. Since JSON schemas in Singer taps often contain complex
anyOf
unions for flexible typing, the optimization significantly benefits the hot path where schemas with nested or multiple
anyOf
branches are processed repeatedly during data transformation pipelines. Trade-offs: • Simple schemas (direct type matches) are 11-30% slower due to stack initialization overhead • However, real-world schemas with
anyOf
unions see 35-2000% improvements, making this optimization highly valuable for the common case in Singer SDK usage ✅ Correctness verification report: | Test | Status | | ----------------------------- | --------------- | | ⚙️ Existing Unit Tests | 🔘 None Found | | 🌀 Generated Regression Tests | ✅ 86 Passed | | ⏪ Replay Tests | 🔘 None Found | | 🔎 Concolic Coverage Tests | 🔘 None Found | | 📊 Tests Coverage | 100.0% | 🌀 Click to see Generated Regression Tests from future import annotations from singer_sdk.typing import _jsonschema_type_check def test_scalar_type_matches_exact_string(): # A schema that directly specifies a scalar "type" that matches the type_check tuple schema = {"type": "string"} # Expect True because "string" is in the provided type_check tuple codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 333ns -> 416ns (20.0% slower) def test_scalar_type_does_not_match(): # A schema that directly specifies a scalar "type" that does not match schema = {"type": "integer"} # Expect False because "string" is not present codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 708ns -> 541ns (30.9% faster) def test_type_field_as_list_matches_one_element(): # "type" can be a list; one of the list elements should match type_check schema = {"type": ["number", "string", "null"]} # Expect True because "string" is present in the "type" list codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 375ns -> 458ns (18.1% slower) def test_type_field_as_tuple_matches(): # "type" may also be a tuple and should be handled the same as a list schema = {"type": ("null",)} # Expect True because "null" is in the tuple codeflash_output = _jsonschema_type_check( schema, ("null",) ) # 375ns -> 417ns (10.1% slower) def test_empty_schema_returns_false(): # No "type" key and no "anyOf" -> should return False schema = {} codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 541ns -> 375ns (44.3% faster) def test_type_present_but_non_matching_then_anyof_matches(): # If "type" is present but not matching, the function still checks "anyOf" schema = {"type": "boolean", "anyOf": [{"type": "string"}]} # Expect True because although top-level "type" doesn't match, an anyOf branch does codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 875ns -> 708ns (23.6% faster) def test_type_present_matches_short_circuits_and_returns_true_even_if_anyof_absent_or_nonmatching(): # If "type" matches, function should return True even if anyOf would not match schema = {"type": "string", "anyOf": [{"type": "integer"}]} codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 333ns -> 375ns (11.2% slower) def test_anyof_with_multiple_entries_none_match_returns_false(): # anyOf contains multiple schemas none of which match the requested type_check schema = {"anyOf": [{"type": "foo"}, {"type": "bar"}, {"type": ["baz", "qux"]}]} codeflash_output = _jsonschema_type_check( schema, ("not-present",) ) # 1.71μs -> 1.21μs (41.3% faster) def test_type_is_none_but_anyof_matches(): # A non-standard case where "type" is None - the function treats it as non-matching # and still falls back to checking anyOf schema = {"type": None, "anyOf": [{"type": "number"}]} codeflash_output = _jsonschema_type_check( schema, ("number",) ) # 917ns -> 750ns (22.3% faster) def test_top_level_type_non_matching_and_no_anyof_returns_false(): # If "type" exists and doesn't match and there is no anyOf -> False schema = {"type": "integer"} codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 667ns -> 500ns (33.4% faster) def test_anyof_contains_nested_anyof_that_matches(): # anyOf entries themselves can contain anyOf; function recurses into those entries schema = { "anyOf": [ {"anyOf": [{"type": "foo"}, {"type": "bar"}]}, {"anyOf": [{"type": "string"}]}, ] } codeflash_output = _jsonschema_type_check( schema, ("string",) ) # 1.88μs -> 750ns (150% faster) def test_large_anyof_list_iteration_find_match_near_end(): # Build a shallow anyOf list with 1000 entries where only the last one matches. # This verifies performance on a large flat structure (no deep recursion). large_anyof = [{"type": "nope"} for _ in range(999)] large_anyof.append({"type": "target_type"}) # last element will match schema = {"anyOf": large_anyof} # Ensure the function returns True scanning through many entries codeflash_output = _jsonschema_type_check( schema, ("target_type",) ) # 210μs -> 10.0μs (1996% faster) def test_large_anyof_all_nonmatching_returns_false(): # Large anyOf list with 1000 non-matching entries should return False large_anyof = [{"type": "a"} for _ in range(1000)] schema = {"anyOf": large_anyof} codeflash_output = _jsonschema_type_check( schema, ("z",) ) # 213μs -> 109μs (95.2% faster) def test_deeply_nested_anyof_recurses_and_finds_match(): # Build a nested anyOf chain depth 50, where the deepest nested schema contains the matching type. depth = 50 nested = {"type": "bottom_match"} # Wrap nested dicts inside anyOf arrays repeatedly (each level contains a single dict) for _ in range(depth): nested = {"anyOf": [nested]} # Now nested is deeply wrapp… meltano/sdk