Skip to content

refactor: optimize performance for hand calculations#189

Merged
Apricot-S merged 6 commits intomasterfrom
optimize-performance-v2
Feb 6, 2026
Merged

refactor: optimize performance for hand calculations#189
Apricot-S merged 6 commits intomasterfrom
optimize-performance-v2

Conversation

@Nihisil
Copy link
Contributor

@Nihisil Nihisil commented Feb 6, 2026

I think it is the latest round of optimizations. All low-hanging fruit have been picked (only removal of is_agari remained, but it would be done in separate PR).

We can optimize it further for sure, but it would require more invasive changes to the architecture, and the goal of this lib is not to be the fastest mahjong lib out there, but rather a good balance of speed, correctness, and maintainability. For super fast libs there are Rust/C versions available.

For example, we can get a lot of performance gains by getting rid of Yaku.is_condition_met() and just pre-calculate all honors, suits and etc per hand and use these ints to calculate all yaku, but it is not the change that I want to do in this lib.

Summary of optimization patterns used:

  • Algorithmic improvements: O(n^2) → O(n) via dictionary counting and bitmask approach
  • Data structure upgrades: list → frozenset/set for O(1) membership, bitmask for intersection
  • Pass reduction: Multiple iterations collapsed into single-pass logic
  • Some hand yaku pre-checks to avoid not necessary calculations, mainly based on https://riichi.wiki/Yaku_compatibility

And all 2.1kk validation hands passed successfully.

Benchmark Results

Benchmark was run with n=5, limit=200000.

Old

  • Throughput: 28313 hands/sec (based on median)
  • Avg per hand: 0.035ms (based on median)

New

  • Throughput: 30985 hands/sec (based on median)
  • Avg per hand: 0.032ms (based on median)

Overall profile

Metric Old New Change
Total profile time 15.691s 14.021s -10.6%
Total profile calls 67,801,516 56,573,351 -16.6%

estimate_hand_value function

Metric Old New Change
Own time 2.964s 2.462s -16.9%
Cumulative time 15.645s 13.964s -10.7%
Callee calls 12,852,409 10,221,010 -20.5%
Callee tottime 5.174s 4.544s -12.2%
Callee cumtime 12.680s 11.502s -9.3%

@Nihisil Nihisil added this to the v2.0.0 milestone Feb 6, 2026
@Nihisil Nihisil requested a review from Apricot-S February 6, 2026 06:36
@Nihisil Nihisil changed the title refactor: optimize performance for hand refactor: optimize performance for hand calculations Feb 6, 2026
@Nihisil Nihisil requested a review from Apricot-S February 6, 2026 07:40
Copy link
Collaborator

@Apricot-S Apricot-S left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Apricot-S Apricot-S merged commit 299051f into master Feb 6, 2026
8 checks passed
@Apricot-S Apricot-S deleted the optimize-performance-v2 branch February 6, 2026 07:43
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