Commit 7b440d50 authored by Luke Mewburn's avatar Luke Mewburn
Browse files

compat_asn1: cache ASN.1 parsing

Implement caches for _parse_asn1_commit() and _parse_asn1_files().
Avoids re-running git and reading the files if the same item is parsed.
Speeds up the compat checking in asn_process by ~25%.
parent 4f81e7c3
Loading
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -139,6 +139,10 @@ class CompatCheck:

    def __init__(self):
        """Construct CompatCheck."""
        # key is (commit, filename, tuple(dependencies)), value is parsed ASN1Dict
        self._cache_commits = {}
        # key is tuple(filenames), value is parsed ASN1Dict
        self._cache_files = {}
        self._clear()

    def _clear(self) -> None:
@@ -191,21 +195,33 @@ class CompatCheck:
    ) -> pa_asnobj.ASN1Dict:
        """Parse `asn_file` as at git commit `commit` as ASN.1 using pycrate, returning the module object."""
        logging.info(f"Parsing {asn_file} as at git commit {commit}")
        cachekey = (commit, asn_file, tuple(dependencies))
        if (cached_parse := self._cache_commits.get(cachekey, None)) is not None:
            logging.info(f"Parse cache hit with key {cachekey}")
            return cached_parse
        asn_text = []
        asn_text.append(self._read_commit(commit=commit, filename=asn_file))
        filenames = [asn_file]
        for filename in dependencies:
            asn_text.append(self._read_file(filename))
            filenames.append(filename)
        return self._parse_asn1_text(asn_text=asn_text, filenames=filenames)
        parse = self._parse_asn1_text(asn_text=asn_text, filenames=filenames)
        self._cache_commits[cachekey] = parse
        return parse

    def _parse_asn1_files(self, asn_files: list[str]) -> pa_asnobj.ASN1Dict:
        """Parse `asn_files` as ASN.1 using pycrate, returning the module object."""
        logging.info(f"Parsing {' '.join(asn_files)}")
        cachekey = tuple(asn_files)
        if (cached_parse := self._cache_files.get(cachekey, None)) is not None:
            logging.info(f"Parse cache hit with key {cachekey}")
            return cached_parse
        asn_text = []
        for filename in asn_files:
            asn_text.append(self._read_file(filename))
        return self._parse_asn1_text(asn_text=asn_text, filenames=asn_files)
        parse = self._parse_asn1_text(asn_text=asn_text, filenames=asn_files)
        self._cache_files[cachekey] = parse
        return parse

    def _container_to_tag_dict(self, container: pa_asnobj.ASN1Dict) -> dict:
        """Convert `container` to dict indexed on tag, value is type."""