Skip to contentSkip to conversation

DT validation time improvements

PATCH New Rob Herring 1 participant 4 messages Aug 14, 2020

Subsystems (2)
lore
Share & tools
lore

Rob Herring

author maintainer
#0 lore raw

cover 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
author maintainer
#1 lore raw

PATCH 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
index 91c4d00e96d3..6a678eb5b5cd 100644
@@ -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
author maintainer
#2 lore raw

PATCH 2/3 dt-bindings: Use json for processed-schema*

In reply to Rob Herring

From: 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
index 5c6d8ea1a09c..3a05b99bfa26 100644
@@ -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
index 6a678eb5b5cd..bedc2210a2e0 100644
@@ -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
index 3d599716940c..94133708889d 100644
@@ -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
author maintainer
#3 lore raw

PATCH 3/3 dt-bindings: Validate DT binding schema in a single call

In reply to Rob Herring

As 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
index bedc2210a2e0..d21c4c4f9eee 100644
@@ -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