Skip to content

simplify definitions.rs - #826

Open
moritz-gross wants to merge 3 commits into
daisy:mainfrom
moritz-gross:simplify-definitions-rs
Open

moritz-gross wants to merge 3 commits into
daisy:mainfrom
moritz-gross:simplify-definitions-rs

Conversation

@moritz-gross

Copy link
Copy Markdown
Collaborator

some more ideas on how to simplify definitions.rs:

  • we have duplicate, manually written constructors for Definitions that specify default capacity of 30 elements
    • from my experience with data structures in Rust and in general, specifying any starting value below like 10_000 not noticeable. As the creation of the hashmap only happens briefly once at the start anyway, I suggest just cutting this magic number, but I'd be interested if you had contradicting experiences
  • use of unwrap_or
  • in build_all_functions_set manually inserting each element using a loop likely has a worse performance impact than not specifying the starting capacity, I think

@NSoiffer

Copy link
Copy Markdown
Collaborator

I don't like the change of removing the initial default. Hashtables typically start small and then have to do reallocations and copying each time they grow (typically by a power of 2). In MathCAT, this mainly happens during startup, which is the slowest part of MathCAT. I'd rather waste a few hundred bytes of unused storate than a few milliseconds during startup. Also, a larger hashtable has fewer collisions, so is faster. That means the space might not be "wasted".

It makes sense to periodically look at what the size of the hashtables are in real life and adjust the size accordingly. I've done that a few times with the Unicode tablesSD . I've purposely made them larger than need to make sure hashing is fast. As you probably know, things that are done on the leaves of a tree almost always dominate computation time/space. It would be good to revisit the size of definitions hashtables and see if 30 is right... which it isn't. I just got AI to tell me that Rust will adjust that size by 8/7 to maintain some space in the table, and then round up to a power of two since all tables are sized to be powers of 2. So 30 => 28, or if it should be larger, 56 or 112 (unlikely).

"IntentMapings" is probably the largest HashMap and to avoid having lots of extra room for the other tables, perhaps it should be special-cased or it can be the exception that resizes. If one table resizes (besides the Unicode ones), that's not a big deal.

@moritz-gross

moritz-gross commented Sep 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

I see where you are coming from, but manually tuning data structures is often way more tricky than it looks to be at first.
For example, Rust uses a port of the SwissTable design, which does some fancy SIMD stuff and is supposed to remain fast even at higher occupancy. So here, manually tweaking the table may provide no or unintended effects.

In my Masters studies, I worked with Sebastian Wild, a Prof. for algorithms and data structures, whose work now also powers sorting in Python and NumPy for example. If performance of MathCAT grows to a bigger concern, I can set up a consulting call with him. I've mentioned my work on MathCAT to him already, so he's familiar with the project a bit.

So for this PR: That means I'll restore the impl Default for Definitions, but we can drop the duplicated fn new() -> Self right?

@github-actions

Copy link
Copy Markdown
Linux library size: 0.58 MiB (-0.02%)
Revision Release liblibmathcat.so
Base (89d018b) 0.58 MiB (605,448 bytes)
PR (62cabb4) 0.58 MiB (605,328 bytes)
Change -120 bytes (-0.02%)

Built with default features, Rust 1.96.0, and Ubuntu 24.04. Workflow run.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

2 participants