Skip to content

Commit

Permalink
Unroll properties of 1 keyword even more aggressively (#1199)
Browse files Browse the repository at this point in the history
Signed-off-by: Juan Cruz Viotti <[email protected]>
  • Loading branch information
jviotti authored Sep 17, 2024
1 parent d57beae commit 3785582
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 101 deletions.
20 changes: 20 additions & 0 deletions src/jsonschema/compile_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <sourcemeta/jsontoolkit/jsonschema_compile.h>

#include <cassert> // assert
#include <utility> // std::declval, std::move

namespace sourcemeta::jsontoolkit {
Expand Down Expand Up @@ -52,6 +53,25 @@ auto make(const bool report, const SchemaCompilerContext &context,
std::move(children)};
}

template <typename Type, typename Step>
auto unroll(const SchemaCompilerDynamicContext &dynamic_context,
const Step &step,
const Pointer &base_instance_location = empty_pointer) -> Type {
assert(std::holds_alternative<Type>(step));
return {dynamic_context.keyword.empty()
? std::get<Type>(step).relative_schema_location
: dynamic_context.base_schema_location
.concat({dynamic_context.keyword})
.concat(std::get<Type>(step).relative_schema_location),
base_instance_location.concat(
std::get<Type>(step).relative_instance_location),
std::get<Type>(step).keyword_location,
std::get<Type>(step).schema_resource,
std::get<Type>(step).dynamic,
std::get<Type>(step).report,
std::get<Type>(step).value};
}

} // namespace sourcemeta::jsontoolkit

#endif
34 changes: 30 additions & 4 deletions src/jsonschema/default_compiler_draft4.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,24 +428,42 @@ auto compiler_draft4_applicator_properties_conditional_annotation(

// Optimize `properties` where its subschemas just include a type check,
// as that's a very common pattern

} else if (substeps.size() == 1 &&
std::holds_alternative<SchemaCompilerAssertionTypeStrict>(
substeps.front())) {
const auto &type_step{
std::get<SchemaCompilerAssertionTypeStrict>(substeps.front())};
children.push_back(SchemaCompilerAssertionPropertyTypeStrict{
type_step.relative_schema_location,
type_step.relative_instance_location, type_step.keyword_location,
type_step.schema_resource, type_step.dynamic, true, type_step.value});
dynamic_context.base_instance_location.concat(
type_step.relative_instance_location),
type_step.keyword_location, type_step.schema_resource,
type_step.dynamic, type_step.report, type_step.value});
} else if (substeps.size() == 1 &&
std::holds_alternative<SchemaCompilerAssertionType>(
substeps.front())) {
const auto &type_step{
std::get<SchemaCompilerAssertionType>(substeps.front())};
children.push_back(SchemaCompilerAssertionPropertyType{
type_step.relative_schema_location,
type_step.relative_instance_location, type_step.keyword_location,
type_step.schema_resource, type_step.dynamic, true, type_step.value});
dynamic_context.base_instance_location.concat(
type_step.relative_instance_location),
type_step.keyword_location, type_step.schema_resource,
type_step.dynamic, type_step.report, type_step.value});
} else if (substeps.size() == 1 &&
std::holds_alternative<
SchemaCompilerAssertionPropertyTypeStrict>(
substeps.front())) {
children.push_back(unroll<SchemaCompilerAssertionPropertyTypeStrict>(
relative_dynamic_context, substeps.front(),
dynamic_context.base_instance_location));
} else if (substeps.size() == 1 &&
std::holds_alternative<SchemaCompilerAssertionPropertyType>(
substeps.front())) {
children.push_back(unroll<SchemaCompilerAssertionPropertyType>(
relative_dynamic_context, substeps.front(),
dynamic_context.base_instance_location));

} else {
children.push_back(make<SchemaCompilerLogicalWhenDefines>(
Expand All @@ -454,6 +472,14 @@ auto compiler_draft4_applicator_properties_conditional_annotation(
}
}

// Optimize away the wrapper when emitting a single instruction
if (children.size() == 1 &&
std::holds_alternative<SchemaCompilerAssertionPropertyTypeStrict>(
children.front())) {
return {unroll<SchemaCompilerAssertionPropertyTypeStrict>(
dynamic_context, children.front())};
}

return {make<SchemaCompilerLogicalAnd>(
true, context, schema_context, dynamic_context, SchemaCompilerValueNone{},
std::move(children))};
Expand Down
Loading

4 comments on commit 3785582

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/llvm)

Benchmark suite Current: 3785582 Previous: d57beae Ratio
JSONSchema_Validate_Draft4_Meta_1_No_Callback 658.8367913349689 ns/iter 712.0638280563484 ns/iter 0.93
JSONSchema_Validate_Draft4_Required_Properties 785.7233159090523 ns/iter 860.0134957838867 ns/iter 0.91
JSONSchema_Validate_Draft4_Many_Optional_Properties_Minimal_Match 142.33482783381845 ns/iter 157.6024011608068 ns/iter 0.90
JSONSchema_Validate_Draft4_Few_Optional_Properties_Minimal_Match 105.17191899110043 ns/iter 156.3305403420152 ns/iter 0.67
JSONSchema_Validate_Draft4_Items_Schema 1954.208437470312 ns/iter 2140.7352745969624 ns/iter 0.91
JSONSchema_Validate_Draft4_Nested_Object 1212.0592334015541 ns/iter 1359.2380229917974 ns/iter 0.89
JSONSchema_Validate_Draft4_Properties_Triad_Optional 1329.8401704453045 ns/iter 1465.9598542346614 ns/iter 0.91
JSONSchema_Validate_Draft4_Properties_Triad_Closed 989.5349437892426 ns/iter 1098.2583955076814 ns/iter 0.90
JSONSchema_Validate_Draft4_Properties_Triad_Required 1340.8189848273337 ns/iter 1461.8615209899222 ns/iter 0.92
JSONSchema_Validate_Draft4_Non_Recursive_Ref 477.1638922273727 ns/iter 526.065208999853 ns/iter 0.91
JSONSchema_Validate_Draft4_Pattern_Properties_True 1308.491412048002 ns/iter 1424.9182679342043 ns/iter 0.92
JSONSchema_Validate_Draft4_Ref_To_Single_Property 108.49923418528799 ns/iter 163.08370811844864 ns/iter 0.67

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/llvm)

Benchmark suite Current: 3785582 Previous: d57beae Ratio
JSONSchema_Validate_Draft4_Meta_1_No_Callback 16565.434060824122 ns/iter 16421.91511158993 ns/iter 1.01
JSONSchema_Validate_Draft4_Required_Properties 6678.853178279034 ns/iter 6661.345692395457 ns/iter 1.00
JSONSchema_Validate_Draft4_Many_Optional_Properties_Minimal_Match 1889.6647225091783 ns/iter 1781.9400980551636 ns/iter 1.06
JSONSchema_Validate_Draft4_Few_Optional_Properties_Minimal_Match 868.3611936509324 ns/iter 1652.4360867711086 ns/iter 0.53
JSONSchema_Validate_Draft4_Items_Schema 114592.56199547891 ns/iter 112901.5113801437 ns/iter 1.01
JSONSchema_Validate_Draft4_Nested_Object 52827.79427793012 ns/iter 52980.26901248326 ns/iter 1.00
JSONSchema_Validate_Draft4_Properties_Triad_Optional 8602.46395288738 ns/iter 8452.999493139536 ns/iter 1.02
JSONSchema_Validate_Draft4_Properties_Triad_Closed 8047.682909750145 ns/iter 7918.159417671355 ns/iter 1.02
JSONSchema_Validate_Draft4_Properties_Triad_Required 8763.375446038732 ns/iter 8660.196784073205 ns/iter 1.01
JSONSchema_Validate_Draft4_Non_Recursive_Ref 4212.329836892985 ns/iter 4183.269841550406 ns/iter 1.01
JSONSchema_Validate_Draft4_Pattern_Properties_True 6062.716165251205 ns/iter 5989.532055575493 ns/iter 1.01
JSONSchema_Validate_Draft4_Ref_To_Single_Property 877.330995449429 ns/iter 1661.6891447290402 ns/iter 0.53

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/gcc)

Benchmark suite Current: 3785582 Previous: d57beae Ratio
JSONSchema_Validate_Draft4_Meta_1_No_Callback 1150.1157964673541 ns/iter 1105.0562477749472 ns/iter 1.04
JSONSchema_Validate_Draft4_Required_Properties 2179.16366254507 ns/iter 2181.335805032025 ns/iter 1.00
JSONSchema_Validate_Draft4_Many_Optional_Properties_Minimal_Match 222.1631592103254 ns/iter 191.36697468707422 ns/iter 1.16
JSONSchema_Validate_Draft4_Few_Optional_Properties_Minimal_Match 154.4391608795456 ns/iter 211.71105968221605 ns/iter 0.73
JSONSchema_Validate_Draft4_Items_Schema 3600.1140139230547 ns/iter 3562.2429042770095 ns/iter 1.01
JSONSchema_Validate_Draft4_Nested_Object 1724.2939608100148 ns/iter 1721.4206104615118 ns/iter 1.00
JSONSchema_Validate_Draft4_Properties_Triad_Optional 1790.6552228390751 ns/iter 1747.7580652429906 ns/iter 1.02
JSONSchema_Validate_Draft4_Properties_Triad_Closed 1485.390859839454 ns/iter 1440.4425341478293 ns/iter 1.03
JSONSchema_Validate_Draft4_Properties_Triad_Required 1867.1938599250702 ns/iter 1827.1298579685326 ns/iter 1.02
JSONSchema_Validate_Draft4_Non_Recursive_Ref 763.119013935854 ns/iter 758.9195430973797 ns/iter 1.01
JSONSchema_Validate_Draft4_Pattern_Properties_True 2293.6735920464803 ns/iter 2413.6076486422517 ns/iter 0.95
JSONSchema_Validate_Draft4_Ref_To_Single_Property 166.14221526556827 ns/iter 223.5325863342504 ns/iter 0.74

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (windows/msvc)

Benchmark suite Current: 3785582 Previous: d57beae Ratio
JSONSchema_Validate_Draft4_Meta_1_No_Callback 3032.164774438195 ns/iter 3022.048214284772 ns/iter 1.00
JSONSchema_Validate_Draft4_Required_Properties 1636.1217168830967 ns/iter 1651.6879464286865 ns/iter 0.99
JSONSchema_Validate_Draft4_Many_Optional_Properties_Minimal_Match 616.2248214286998 ns/iter 629.6154464284394 ns/iter 0.98
JSONSchema_Validate_Draft4_Few_Optional_Properties_Minimal_Match 427.71791504525777 ns/iter 589.7159000001011 ns/iter 0.73
JSONSchema_Validate_Draft4_Items_Schema 11542.885714285538 ns/iter 12009.349999999586 ns/iter 0.96
JSONSchema_Validate_Draft4_Nested_Object 6545.711607143647 ns/iter 6574.740178572419 ns/iter 1.00
JSONSchema_Validate_Draft4_Properties_Triad_Optional 5671.5749999989375 ns/iter 5639.312999999219 ns/iter 1.01
JSONSchema_Validate_Draft4_Properties_Triad_Closed 4715.052935386061 ns/iter 4694.440612590438 ns/iter 1.00
JSONSchema_Validate_Draft4_Properties_Triad_Required 5709.127678571235 ns/iter 5714.669000001322 ns/iter 1.00
JSONSchema_Validate_Draft4_Non_Recursive_Ref 1154.4870312501841 ns/iter 1164.147142856921 ns/iter 0.99
JSONSchema_Validate_Draft4_Pattern_Properties_True 7882.447399788681 ns/iter 7894.6562499991405 ns/iter 1.00
JSONSchema_Validate_Draft4_Ref_To_Single_Property 432.53106250006107 ns/iter 590.3569642857829 ns/iter 0.73

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.