Skip to content

Spread bits in computing bucket index - #163

Merged
liufengyun merged 3 commits into
mainfrom
hashing
Oct 17, 2026
Merged

liufengyun merged 3 commits into
mainfrom
hashing

Conversation

@liufengyun

@liufengyun liufengyun commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Spread bits in computing bucket index

Summary

This is a common optimization in power-of-two hash tables (%16, %32, etc.), to distribute hash codes that have similar lower bits but different high bits more evenly.

This is a performance improvement. The following test is an extreme case, but it does show the optimization pays off:

Backend Before After Speedup
Ruby 11.33 s 0.349 s 32.5×
Python 14.09 s 0.347 s 40.6×
JavaScript (Node.js) 0.280 s 0.131 s 2.1×
JavaScript (Node.js, --jitless) 14.68 s 0.493 s 29.8×

4,000 distinct Long values (i << 32). Median of five runs after one warm-up.

Checklist

  • Added / updated tests under tests/pos/ or tests/warn/
  • Docs updated if the change affects user-visible behavior
  • A JIP is required for language change
  • All commits are signed off (why?)
How to sign off commits

Use git commit -s to add the Signed-off-by line automatically:

To add a sign-off to the last commit retroactively:

git commit --amend -s --no-edit

To add sign-off to the last 3 commits:

git rebase --signoff HEAD~3

Security impact

No

Compatibility impact

No

  • Source compatibility
    • syntax parsing
    • type checking
  • SAST compatibility
    • forward compatibility: new libraries can be used by old compiler
    • backward comopatibility: old libraries can be used by new compiler
  • Standard Library compatibility:
    • forward compatibility: new code can work with old stdlib
    • backward compatibility: old code work with the new stdlib
  • Runtime Library compatibility:
    • forward compatibility: new code can work with old runtime
    • backward compatibility: old code work with the new runtime
  • Build tool
    • Build spec compatibility: old projects continue to build
    • Joy package compatibility: old .joy can be consumed by new build tool

Signed-off-by: Fengyun Liu <fengyun.liu.cs@gmail.com>
Signed-off-by: Fengyun Liu <fengyun.liu.cs@gmail.com>
Signed-off-by: Fengyun Liu <fengyun.liu.cs@gmail.com>
@liufengyun
liufengyun requested a balanced review from Copilot October 17, 2026 16:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@liufengyun
liufengyun requested a review from everdance October 17, 2026 16:46
@liufengyun
liufengyun added this pull request to stack #165 October 17, 2026 17:55
Comment thread lib/mutable/Set.jo
Comment on lines +75 to +77
val h = hash.hashCode(x)
val spread = h ^ ((h >> 16) & 0xffff)
(spread & 0x7fffffff) % cap

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

we should ensure cap is prime number

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is more important than the hash code value

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Using prime number is a design choice, but not the only one. Here we are following the common design that use power-of-two capacity and spread higher-bits.

It's used e.g. in JDK: https://github.com/openjdk/jdk/blob/8610e806260f4eec6d98a5b418e4a1bc11a9a3cb/src/java.base/share/classes/java/util/HashMap.java#L320-L339

@liufengyun
liufengyun merged commit ff265be into main Oct 17, 2026
1 check passed
@liufengyun
liufengyun deleted the hashing branch October 17, 2026 20:22
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.

3 participants