From c310d29fc4fa37d6f3e1e49a063c50d36b20b62a Mon Sep 17 00:00:00 2001 From: Nathaniel Graff Date: Thu, 23 Jan 2020 13:48:15 -0800 Subject: [PATCH] Remove bound on parser memoization cache Improve parser performance by removing bound on the memoization cache Adds the environment variable option PYDEVICETREE_CACHE_SIZE_BOUND which can be used to limit the memoization cache if necessary. Signed-off-by: Nathaniel Graff --- .github/workflows/tests.yml | 3 +++ Makefile | 5 +++++ pydevicetree/source/grammar.py | 16 ++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 004e6af..8701889 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,6 +32,9 @@ jobs: - name: Run unit tests run: make test-unit + - name: Run unit tests with bounded parser cache + run: + make test-cache-size-bound - name: Run integration tests run: make test-integration diff --git a/Makefile b/Makefile index 7d9a39e..74676ca 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,11 @@ test-unit: venv/bin/activate $(UNIT_TESTS) . $< && python3 -m unittest $(UNIT_TESTS) test: test-unit +.PHONY: test-cache-size-bound +test-cache-size-bound: venv/bin/activate $(UNIT_TESTS) + PYDEVICETREE_CACHE_SIZE_BOUND=128 . $< && python3 -m unittest $(UNIT_TESTS) +test: test-cache-size-bound + INTEGRATION_TESTS = tests/test_full_trees.py .PHONY: test-integration diff --git a/pydevicetree/source/grammar.py b/pydevicetree/source/grammar.py index 7768439..cabf917 100644 --- a/pydevicetree/source/grammar.py +++ b/pydevicetree/source/grammar.py @@ -2,9 +2,22 @@ # Copyright (c) 2019 SiFive Inc. # SPDX-License-Identifier: Apache-2.0 +import os +import sys + import pyparsing as p # type: ignore -p.ParserElement.enablePackrat() +ENV_CACHE_OPTION = "PYDEVICETREE_CACHE_SIZE_BOUND" + +cache_bound = None +if ENV_CACHE_OPTION in os.environ: + option = os.environ[ENV_CACHE_OPTION] + if option != "None": + try: + cache_bound = int(option) + except ValueError: + print("%s requires a valid integer" % ENV_CACHE_OPTION, file=sys.stderr) +p.ParserElement.enablePackrat(cache_bound) node_name = p.Word(p.alphanums + ",.-+_") ^ p.Literal("/") integer = p.pyparsing_common.integer ^ (p.Literal("0x").suppress() + p.pyparsing_common.hex_integer) @@ -59,6 +72,5 @@ devicetree.ignore("//" + p.SkipTo(p.lineEnd)) if __name__ == "__main__": - import sys if len(sys.argv) > 1: devicetree.parseFile(sys.argv[1]).pprint()