Simplify name tagger cache and align tests with production flags - #262
Simplify name tagger cache and align tests with production flags#262trungminhdo4-glitch wants to merge 1 commit into
Conversation
Replace the flag-keyed RwLock<HashMap<(TaggerKind, Normalize), Arc<Tagger>>> cache with two LazyLock<Tagger> statics (Org, Person) built with the production-normalisation flags (CASEFOLD | NAME). The tagger has no Python surface and is only driven by analyze_names with a constant flag combination, so the per-flag cache was guarding against a use-case that never materialised. Two statics remove the lock, map, key hashing, and unnecessary dynamic dispatching. - Drop the RwLock/HashMap/Arc cache and its read/write lock overhead - Add ORG_TAGGER and PERSON_TAGGER statics initialised lazily - Move TAGGER_FLAGS to tagger.rs as pub(crate) const - Re-pin tests to use the same flags as production
|
@trungminhdo4-glitch csn you confirm that you've read this PR and are prepared to explain it? |
|
Yes, I have read the full PR and I am prepared to explain it. I also want to be transparent that I used AI assistance to help analyze the issue, inspect the relevant code paths, and develop the proposed solution. I did not intend to present the changes as work I had not reviewed: I read the resulting diff, checked the repository-wide call sites and assumptions, and ran the formatting, Clippy, and Rust test suite myself before opening the PR. My understanding of the change is:
I ran:
If this repository prohibits or requires a specific disclosure for AI-assisted contributions and I missed that rule, I apologize. I am happy to follow your preferred process, revise the PR, provide a more detailed explanation of any part of the change, or close it if that is the appropriate action. |
|
We're not against AI contributions, we just get a ton of fully Claude generated PRs that only exist for contribution farming and that take a ton of time to get merged and make a shit time for our team. Do you think this one here has a real perf or correctness impact? |
|
Thanks for asking directly. I ran a small local A/B benchmark to answer this honestly rather than relying on theory about lock removal. Setup: rustc 1.93.1, Intel i7-8700 @ 3.20GHz, Hot
End-to-end tagging (200K calls/sample, 5 text inputs — "siemens aktiengesellschaft", "acme number one limited", "john smith", "isa bin tarif al bin ali", plus a no-hit case):
Cold initialization (15 processes per variant):
Conclusion: there is a real, measurable microbenchmark difference in the accessor, but it does not produce a meaningful end-to-end performance improvement. The PR also does not fix a reproduced correctness bug; the correctness-adjacent benefit is only that the tests now exercise the same configuration as production. So I would characterize this as a cleanup, not a material performance or correctness improvement. It was useful for me to investigate, but I understand that this alone may not justify your team's review and maintenance cost. I am fine with closing it if it does not meet your bar. |
Problem
The tagger cache in
rust/src/names/tagger.rswas anRwLock<HashMap<(TaggerKind, Normalize), Arc<Tagger>>>-- justified by a comment as "same shape as the org_types Replacer cache". The analogy doesn't hold: the Replacer receives arbitrary flags over FFI from Python, while the tagger has no Python surface at all. Its only production caller isanalyze_nameswith the constantTAGGER_FLAGS(CASEFOLD | NAME).Additionally, the unit tests built automatons with
CASEFOLD | SQUASH_SPACES-- a combination pinned to a Python wrapper default that no longer exists. All tagger tests therefore exercised a configuration production never runs.Changes
RwLock<HashMap<...>>,TaggerCachetype alias, andTAGGER_CACHEstatic are all removed.LazyLock<Tagger>statics:ORG_TAGGERandPERSON_TAGGER, built withTAGGER_FLAGS(CASEFOLD | NAME).get_tagger: Now takes onlyTaggerKind, returns&'static Tagger.TAGGER_FLAGStotagger.rsaspub(crate) const-- it lives where it's actually consumed.FLAGSconstant and use the same statics your production code uses.reset.py,territories.rs, andperson_names.rs.Why two statics suffice
get_taggerapply_taggerwith a constant flag combinationNormalizeflagsRwLock<HashMap<...>>was guarding against a use-case that never materialisedTest changes
Old test
FLAGSconstant (CASEFOLD | SQUASH_SPACES) replaced by production statics (CASEFOLD | NAME). Pointer-equality tests renamed fromcache_*to reflect static identity. No test expectations required semantic changes -- the test inputs (simple ASCII phrases) normalise identically under both flag combinations.Validation
Risk analysis
LazyLockguarantees thread-safe, single-initialization semantics.get_tagger.Out of scope
Closes #241