DT validation time improvements
Subsystems (2)
Rob Herring
maintainercover DT validation time improvements
The time to run dt_binding_check and dtbs_check has gotten significantly slower as the number of schemas has increased. There's 2 main factors causing validation time on each file to be slow.
The first is python start-up time. This is a common problem for python without much of a solution other than minimizing module imports. Eliminating some imports was possible for dt-extract-example, but not the other tools. Validating multiple files in a single call is the simplest solution. The downside of processing multiple files in one call is losing make dependency handling. This is not too important for dt-doc-validate as the validation time is <10 sec.
The 2nd factor is processed-schema*.yaml is now ~2MB and around 2 sec to parse (which is done for every .dts and example). Switching processed-schema*.yaml to JSON is much faster to parse
The overall result of these changes is a 2x improvement to dtbs_check and a 4-5x improvement to dt_binding_check.
Rob
Andrei Ziureaev (1):
dt-bindings: Use json for processed-schema*
Rob Herring (2):
dt-bindings: Bump minimum version of dtschema to 2020.8
dt-bindings: Validate DT binding schema in a single call
Documentation/devicetree/bindings/.gitignore | 1 + Documentation/devicetree/bindings/Makefile | 45 ++++++++++++-------- scripts/Makefile.lib | 2 +- 3 files changed, 29 insertions(+), 19 deletions(-)
Signature · 1 line
2.25.1
Rob Herring
maintainerPATCH 1/3 dt-bindings: Bump minimum version of dtschema to 2020.8
dtschema release 2020.8 gained several additions to help performance. dt-doc-validate can now take a list of files and directories, and dt-mk-schema can store the processed schema in JSON which is much faster to parse than YAML. Utilizing both of these changes results in a 4-5x speed improvement in running dt_binding_check.
There's also additional meta-schema checks which binding schemas should be checked against.
--- Documentation/devicetree/bindings/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/devicetree/bindings/Makefile +1 -1
@@ -3,7 +3,7 @@ DT_DOC_CHECKER ?= dt-doc-validate DT_EXTRACT_EX ?= dt-extract-example DT_MK_SCHEMA ?= dt-mk-schema -DT_SCHEMA_MIN_VERSION = 2020.5 +DT_SCHEMA_MIN_VERSION = 2020.8 PHONY += check_dtschema_version check_dtschema_version:
Signature · 1 line
2.25.1
Rob Herring
maintainerPATCH 2/3 dt-bindings: Use json for processed-schema*
In reply to Rob HerringFrom: Andrei Ziureaev <[email protected]>
Change the format of processed-schema* from yaml to json to speed up validation. With json output, using xargs and appending the output won't work since json has explicit list begin and end characters. Instead, we pass the schema files as a list in a temp file.
The parsing time for the processed schema goes down from ~2sec to 70ms. Also, 'make dtbs_check' becomes 33% faster.
Some error messages are affected by this change. For example, "True was expected" becomes "... is not of type 'boolean'". The order of messages is also changed.
--- Documentation/devicetree/bindings/.gitignore | 1 + Documentation/devicetree/bindings/Makefile | 25 ++++++++++---------- scripts/Makefile.lib | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-)
Documentation/devicetree/bindings/.gitignore +1 -0
@@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only *.example.dts processed-schema*.yaml +processed-schema*.json
Documentation/devicetree/bindings/Makefile +13 -12
@@ -19,18 +19,19 @@ $(obj)/%.example.dts: $(src)/%.yaml check_dtschema_version FORCE $(call if_changed,chk_binding) # Use full schemas when checking %.example.dts -DT_TMP_SCHEMA := $(obj)/processed-schema-examples.yaml +DT_TMP_SCHEMA := $(obj)/processed-schema-examples.json find_cmd = find $(srctree)/$(src) \( -name '*.yaml' ! \ -name 'processed-schema*' ! \ -name '*.example.dt.yaml' \) quiet_cmd_mk_schema = SCHEMA $@ - cmd_mk_schema = rm -f $@ ; \ + cmd_mk_schema = f=$$(mktemp) ; \ $(if $(DT_MK_SCHEMA_FLAGS), \ echo $(real-prereqs), \ - $(find_cmd)) | \ - xargs $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) >> $@ + $(find_cmd)) > $$f ; \ + $(DT_MK_SCHEMA) -j $(DT_MK_SCHEMA_FLAGS) @$$f > $@ ; \ + rm -f $$f DT_DOCS = $(shell $(find_cmd) | sed -e 's|^$(srctree)/||')
@@ -39,33 +40,33 @@ override DTC_FLAGS := \ -Wno-graph_child_address \ -Wno-interrupt_provider -$(obj)/processed-schema-examples.yaml: $(DT_DOCS) check_dtschema_version FORCE +$(obj)/processed-schema-examples.json: $(DT_DOCS) check_dtschema_version FORCE $(call if_changed,mk_schema) ifeq ($(DT_SCHEMA_FILES),) # Unless DT_SCHEMA_FILES is specified, use the full schema for dtbs_check too. -# Just copy processed-schema-examples.yaml +# Just copy processed-schema-examples.json -$(obj)/processed-schema.yaml: $(obj)/processed-schema-examples.yaml FORCE +$(obj)/processed-schema.json: $(obj)/processed-schema-examples.json FORCE $(call if_changed,copy) DT_SCHEMA_FILES = $(DT_DOCS) else -# If DT_SCHEMA_FILES is specified, use it for processed-schema.yaml +# If DT_SCHEMA_FILES is specified, use it for processed-schema.json -$(obj)/processed-schema.yaml: DT_MK_SCHEMA_FLAGS := -u -$(obj)/processed-schema.yaml: $(DT_SCHEMA_FILES) check_dtschema_version FORCE +$(obj)/processed-schema.json: DT_MK_SCHEMA_FLAGS := -u +$(obj)/processed-schema.json: $(DT_SCHEMA_FILES) check_dtschema_version FORCE $(call if_changed,mk_schema) endif extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES)) extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES)) -extra-$(CHECK_DT_BINDING) += processed-schema-examples.yaml -extra-$(CHECK_DTBS) += processed-schema.yaml +extra-$(CHECK_DT_BINDING) += processed-schema-examples.json +extra-$(CHECK_DTBS) += processed-schema.json # Hack: avoid 'Argument list too long' error for 'make clean'. Remove most of # build artifacts here before they are processed by scripts/Makefile.clean
scripts/Makefile.lib +1 -1
@@ -328,7 +328,7 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE DT_CHECKER ?= dt-validate DT_BINDING_DIR := Documentation/devicetree/bindings # DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile -DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml +DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.json quiet_cmd_dtb_check = CHECK $@ cmd_dtb_check = $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@
Signature · 1 line
2.25.1
Rob Herring
maintainerPATCH 3/3 dt-bindings: Validate DT binding schema in a single call
In reply to Rob HerringAs the number of binding schemas has grown, the time to run dt_binding_check has gotten pretty slow. A large part of this is due to the slow startup time of Python (a well documented problem). There's not currently any benefit to running dt-doc-validate one file at a time, so let's switch it to run a single rule. Doing this means we loose the make parallelism, but we can use xargs instead. This speeds up the validation time from several minutes to <10 sec.
Since the validation is a single step with no output, we move running it as part of the processed-schema-examples.json target. We also need to reorder the extra-y entries so the validation is run first rather than after all the examples are extracted.
--- Documentation/devicetree/bindings/Makefile | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
Documentation/devicetree/bindings/Makefile +15 -7
@@ -11,12 +11,11 @@ check_dtschema_version: $(DT_DOC_CHECKER) --version 2>/dev/null || echo 0; } | sort -VC || \ { echo "ERROR: dtschema minimum version is v$(DT_SCHEMA_MIN_VERSION)" >&2; false; } -quiet_cmd_chk_binding = CHKDT $(patsubst $(srctree)/%,%,$<) - cmd_chk_binding = $(DT_DOC_CHECKER) -u $(srctree)/$(src) $< ; \ - $(DT_EXTRACT_EX) $< > $@ +quiet_cmd_extract_ex = DTEX $@ + cmd_extract_ex = $(DT_EXTRACT_EX) $< > $@ $(obj)/%.example.dts: $(src)/%.yaml check_dtschema_version FORCE - $(call if_changed,chk_binding) + $(call if_changed,extract_ex) # Use full schemas when checking %.example.dts DT_TMP_SCHEMA := $(obj)/processed-schema-examples.json
@@ -25,6 +24,10 @@ find_cmd = find $(srctree)/$(src) \( -name '*.yaml' ! \ -name 'processed-schema*' ! \ -name '*.example.dt.yaml' \) +quiet_cmd_chk_bindings = CHKDT $@ + cmd_chk_bindings = $(find_cmd) | \ + xargs -n200 -P$$(nproc) $(DT_DOC_CHECKER) -u $(srctree)/$(src) + quiet_cmd_mk_schema = SCHEMA $@ cmd_mk_schema = f=$$(mktemp) ; \ $(if $(DT_MK_SCHEMA_FLAGS), \
@@ -33,6 +36,11 @@ quiet_cmd_mk_schema = SCHEMA $@ $(DT_MK_SCHEMA) -j $(DT_MK_SCHEMA_FLAGS) @$$f > $@ ; \ rm -f $$f +define rule_chkdt + $(call cmd,chk_bindings) + $(call cmd,mk_schema) +endef + DT_DOCS = $(shell $(find_cmd) | sed -e 's|^$(srctree)/||') override DTC_FLAGS := \
@@ -41,7 +49,7 @@ override DTC_FLAGS := \ -Wno-interrupt_provider $(obj)/processed-schema-examples.json: $(DT_DOCS) check_dtschema_version FORCE - $(call if_changed,mk_schema) + $(call if_changed_rule,chkdt) ifeq ($(DT_SCHEMA_FILES),)
@@ -63,10 +71,10 @@ $(obj)/processed-schema.json: $(DT_SCHEMA_FILES) check_dtschema_version FORCE endif -extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES)) -extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES)) extra-$(CHECK_DT_BINDING) += processed-schema-examples.json extra-$(CHECK_DTBS) += processed-schema.json +extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES)) +extra-$(CHECK_DT_BINDING) += $(patsubst $(src)/%.yaml,%.example.dt.yaml, $(DT_SCHEMA_FILES)) # Hack: avoid 'Argument list too long' error for 'make clean'. Remove most of # build artifacts here before they are processed by scripts/Makefile.clean
Signature · 1 line
2.25.1