Skip to content

Cache parsed Pitch names; Speedup MusicMXL Style parsing - #2077

Merged
mscuthbert merged 4 commits into
masterfrom
name-cache
Oct 10, 2026
Merged

mscuthbert merged 4 commits into
masterfrom
name-cache

Conversation

@mscuthbert

@mscuthbert mscuthbert commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Faster pitches from names, part of the #2010 speedup work.

  • Pitch.name remembers each string it parses as (step, accidental string, octave), up to 1000 strings, so a repeated name is one dict lookup. Each Pitch still gets its own Accidental.
  • Even the first time, the setter sets the attributes and informs the Note once; a name that fails to parse leaves the pitch unchanged. Names over 100 characters raise a ValueError.
before after
Pitch('F#4'), name seen before 732 ns 355 ns
Pitch('F#4'), name not seen before 735 ns 980 ns
Note('F#4') 1847 ns 1484 ns
<accidental>natural</accidental> import 1378 ns 491 ns
whole tinyNotation, RomanText, ABC, MusicXML files about 1–3% faster
  • unrelated -- but so small we can slip it in: setStyleAttributes returns early for a MusicXML tag with no attributes. 5% faster musicxml parsing on scores without attributes! (5.7ms before for bwv66.6 - 5.4ms after) -- Note that MuseScore writes a position attribute on nearly every tag, so there's no speedup in parsing MuseScore exports.

AI-assisted (Claude)

The .name setter remembers each string it parses as (step, accidental
string, octave) in a module-level dict, cleared at 1000 entries.  A
remembered name sets the attributes directly, makes a new Accidental
(they are mutable, so never shared), and informs the Note once.  Names
that fail to parse are not remembered and raise as before.

Best of 7, master -> branch:
  Pitch('D5')      543 -> 230 ns
  Pitch('F#4')     691 -> 319 ns
  p.name = 'F#4'   556 -> 172 ns
  Note('F#4')     1812 -> 1382 ns

AI-assisted (Claude)
_parseName is now _cacheParsedName: it only parses and remembers (step,
accidental string, octave).  The .name setter reads the cache after a
miss too, so it sets the attributes and informs the Note once even the
first time, and a name that fails to parse leaves the pitch unchanged
(before, D$ changed the step to D and then raised).  Names over 100
characters raise a ValueError, so the cache cannot hold huge strings.

setStyleAttributes returns early for a tag with no attributes (most
<accidental>, <stem>, <type> tags): <accidental>natural</accidental>
1378 -> 491 ns; about 1-3% on whole MusicXML files.

AI-assisted (Claude)
@mscuthbert mscuthbert changed the title Cache parsed Pitch names Cache parsed Pitch names; Speedup MusicMXL Style parsing Oct 10, 2026
@mscuthbert
mscuthbert marked this pull request as ready for review October 10, 2026 04:02
@mscuthbert
mscuthbert merged commit c2f16ce into master Oct 10, 2026
7 checks passed
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 93.375% (+0.001%) from 93.374% — name-cache into master

@mscuthbert
mscuthbert deleted the name-cache branch October 10, 2026 04:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants