From aead415c4e89ead9bbc283c7b75b4cbb8f5aac53 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 2 Sep 2026 17:33:13 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[performance=20improvement]?= =?UTF-8?q?=20Cache=20alias=20lookups=20for=20clinical=20section=20detecti?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: zrt219 <199104500+zrt219@users.noreply.github.com> --- openmed/.jules/bolt.md | 3 +++ openmed/openmed/clinical/sections/detect.py | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 openmed/.jules/bolt.md diff --git a/openmed/.jules/bolt.md b/openmed/.jules/bolt.md new file mode 100644 index 0000000..8fcb703 --- /dev/null +++ b/openmed/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-05-24 - Cache alias lookups for clinical section detection +**Learning:** In `openmed/openmed/clinical/sections/detect.py`, `_alias_lookups` was repeatedly parsing section header lexicons and building dictionaries for each line of a document. For large, many-line documents, this caused significant slowdowns because the section lookup computation is deterministic based on the language. Additionally, since the return values needed caching, a regular dict couldn't be safely cached due to mutability. +**Action:** When caching dictionaries generated from configuration or lexicons, use `@functools.lru_cache` and ensure the return type is explicitly wrapped in `types.MappingProxyType` to prevent any downstream modifications to the cached object. diff --git a/openmed/openmed/clinical/sections/detect.py b/openmed/openmed/clinical/sections/detect.py index 8716746..3293ed0 100644 --- a/openmed/openmed/clinical/sections/detect.py +++ b/openmed/openmed/clinical/sections/detect.py @@ -2,6 +2,8 @@ from __future__ import annotations +import functools +import types from collections.abc import Iterable, Mapping from dataclasses import dataclass from typing import Any @@ -244,6 +246,7 @@ def _is_underline(text: str) -> bool: return len(stripped) >= 3 and set(stripped) <= _UNDERLINE_CHARS +@functools.lru_cache(maxsize=16) def _alias_lookups(language: str | None) -> tuple[tuple[str, Mapping[str, str]], ...]: languages = ( tuple(dict.fromkeys((get_section_lexicon(language).language, "en"))) @@ -253,14 +256,15 @@ def _alias_lookups(language: str | None) -> tuple[tuple[str, Mapping[str, str]], return tuple((code, _aliases_for_language(code)) for code in languages) -def _aliases_for_language(language: str) -> dict[str, str]: +@functools.lru_cache(maxsize=32) +def _aliases_for_language(language: str) -> Mapping[str, str]: lexicon = get_section_lexicon(language) aliases: dict[str, str] = {} for label, headers in lexicon.sections.items(): aliases[normalize_section_header(label)] = label for header in headers: aliases[normalize_section_header(header)] = label - return aliases + return types.MappingProxyType(aliases) def _dedupe_hits(hits: Iterable[_HeaderHit]) -> tuple[_HeaderHit, ...]: