[DNM] Speedy Rust port of the Linux-facing tools - #200
Conversation
Document the repository for AI agents and new contributors: what the project is (core DT schemas + meta-schemas + tooling), the repo layout, the CLI entry points, the two validation flows and the preprocessing/ diagnostics caches, dev setup (venv/pipx for PEP 668 distros), the testing/CI commands, schema-authoring conventions, and how dt-schema plugs into the kernel's dt_binding_check/dtbs_check. Also mirror the kernel's AI-assisted contribution rules (https://docs.kernel.org/process/coding-assistants.html): a human is accountable, agents must not add Signed-off-by, and assistance is disclosed via an Assisted-by trailer. Add a note to keep this file current as the repo evolves. CLAUDE.md is a symlink to AGENTS.md so there is a single source of truth. Assisted-by: Claude Code:opus-4-8 Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
|
Nice!! How do I run this? |
Add an additive Rust port of the dt-schema pipeline under a new rust/ Cargo workspace. The Python package remains authoritative; the Rust tree ports the Linux workflow behaviour and differential-tests against the Python implementation. The Rust workspace contains the dtschema core library plus the five CLIs needed for the kernel binding and DTB validation workflows: dt-mk-schema, dt-doc-validate, dt-validate, dt-extract-example, and dt-check-compatible. The previously explored unused helper tools are intentionally not included. Highlights: - Core library crate (dtschema): YAML loading, binding meta-validation and reference checks, schema fixups, property-type extraction, processed-schema assembly, DTB decoding, gpio/interrupt/address/phandle fixups, DT validation with the custom typeSize keyword, JSON diagnostics, and the per-DTB diagnostics cache. - Validation runs the jsonschema engine directly over decoded devicetree values, using a custom DtJson representation over DtValue so integer bit widths survive for typeSize checks. - Release builds exercise the full Linux workflow with processed schemas and all architecture DTBs/DTBOs, with Rust diagnostics matching Python validation locations. Standard-output/stderr wording is allowed to differ where it is not part of the structured JSON contract. - Tests cover CLI behaviour plus differential parity for fixups, schema processing, DTB decoding, diagnostics, and bundled schema validity. Assisted-by: Claude Code:opus-4-8 Assisted-by: Codex:gpt-5.5 Signed-off-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
|
Each tool is a drop-in replacement for the existing ones, so you should be good to just swap out the bin. For Linux, I used the following hunk. Unfortunately(?) we lose the as-we-go prints with the CHECK make tag, as the tool just crunches everything in a single invocation. Also, for completeness: diff --git a/Makefile b/Makefile
index fc2d94aafb45..47462fcd9d8d 100644
--- a/Makefile
+++ b/Makefile
@@ -1607,11 +1607,24 @@ ifneq ($(filter dtbs_check %.yaml, $(MAKECMDGOALS)),)
export CHECK_DTBS=y
endif
+ifneq ($(CHECK_DTBS),)
+DT_CHECKER ?= dt-validate
+DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),-l $(DT_SCHEMA_FILES),-m)
+endif
+
ifneq ($(CHECK_DTBS),)
dtbs_prepare: dt_binding_schemas
endif
+quiet_cmd_dtbs_check = CHECK $(dtstree)
+ cmd_dtbs_check = f=$$(mktemp); \
+ grep '\.dtb$$' $(objtree)/$(dtstree)/dtbs-list > $$f; \
+ $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(dtbindingtree) \
+ -p $(objtree)/$(dtbindingtree)/processed-schema.json @$$f || true; \
+ rm -f $$f
+
dtbs_check: dtbs
+ $(call cmd,dtbs_check)
dtbs_install:
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.dtbinst obj=$(dtstree)
diff --git a/scripts/Makefile.dtbs b/scripts/Makefile.dtbs
index c4e466390284..251f929fbfed 100644
--- a/scripts/Makefile.dtbs
+++ b/scripts/Makefile.dtbs
@@ -78,7 +78,7 @@ dtb-check-enabled = $(if $(filter %.dtb, $@),y)
endif
quiet_dtb_check_tag = $(if $(dtb-check-enabled),[C], )
-cmd_dtb_check = $(if $(dtb-check-enabled),; $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ || true)
+cmd_dtb_check =
# Overlay
# ---------------------------------------------------------------------------
--
2.54.0 |
|
Humm, A large part of python's slowness is the startup time. That's somewhat mitigated on dt-doc-validate, but not the examples or dtbs. So we could speed up python quite a bit doing the same thing, but I think keeping per target rules is important. Note I just tried out jsonschema-fast last week which uses a rust implementation for validation, but is a drop-in replacement for the python jsonschema module. It was not any faster... |
|
I have 2 thoughts on the general direction for how we would merge/support this. As the schemas and meta-schemas are the only shared part, should we split them out to a separate repo? Then the python and rust implementations can both include it. I suppose we'd have to keep something to test them. Can we make the python executables be thin wrappers to the rust implementation? Then we're not maintaining 2 implementations. This would allow users to just keep doing pip install though you'd still be paying the python startup time penalty (should be a bit less avoiding all the module imports). The rust dependency should be pretty transparent because we already have that dependency indirectly with the referencing module. Need to look at it, but I imagine it's calling cargo from it's pip install. On further thought, maybe better to just put all this in a new repo without any of the python baggage and effort to wrap rust code. Telling folks to run cargo instead of pip isn't that difficult. Hopefully we're beyond having rust as an obstacle. Though I did find this didn't work with debian stable which has rustc 1.85 though there is a 1.95 backport available. |
|
Looks like rust startup is slower than python? For single example dtb, rust is 4x slower: For single large dtbs, rust is about 2x faster with 2 vs 4 sec. There seems to be a 2 sec fixed overhead that needs to be investigated. |
|
I (well, codex did) fixed the slow startup time: https://github.com/robherring/dt-schema.git rust-port A reimplementation of the cache (aka processed-schema.json) gives another incremental improvement. Looks like dt_binding_check is 3-4x faster and arm64 dtbs_check is ~15x faster. |
Processed schema creation and DTB validation are huge bottlenecks in the current kernel maintainer and contributor workflows. This is particularly noticeable when doing work on a machine that's not your main beefy workstation.
In an attempt to remedy these pains, I wanted to explore the room for improvement here. With "a little" help from a robot, this is the final result when validating all 3,873 DTBs and 269 DTBOs present in the Linux kernel (as of some recent -next, for architectures that LLVM supports):
(Running on a Ryzen 6850U in WSL)
As another point of reference, validating all of the 399 qcom DTBs only takes around 2-3s.
The resulting JSON output is equivalent (not necessarily byte-for-byte identical, but equivalent) to the Python reference. The stderr output, similarly, is equivalent (modulo how rust vs python implement Display/repr for certain types).
The Rust implementation of
dt-validateis meant to be run as a single process against an N-long argument list. Parallelism is taken care of through therayoncrate.The question remains, what should we do with this - dumping 6.5k LoC at you and saying "have fun" is obviously missing the point, but particularly the
dt-mk-schemaanddt-validatespeedups are to the point where we could integrate this into an LSP, so I really believe we should think about integrating this seriously.cc @robherring @krzk @quic-bjorande