Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compile-time evaluate constant BitArray int segments on JavaScript #3798

Merged
merged 1 commit into from
Nov 22, 2024

Conversation

richard-viney
Copy link
Contributor

@richard-viney richard-viney commented Nov 6, 2024

Implements #3724.

Details

  1. Ints in bit array expressions with a known value and size at compile time are now evaluated to bytes instead of using sizedInt() at runtime.

  2. Ints in bit array patterns with a known value and size at compile time are now evaluated then matched byte-wise instead of using intFromSlice() at runtime.

  3. The above is currently limited to Int sizes <= 48 bits in order to be under the JS safe integer limit, because otherwise:

    1. Code such as <<0:8192>> would evaluate to [0,0,0,0, ...]to 1024 entries, which seems undesirable (though I'm not sure if such code is commonly encountered).
    2. Code such as let assert <<0xFFFFFFFFFFFFFFFF:64>> == <<255, 255, 255, 255, 255, 255, 255, 255>> would change behaviour, albeit in a correct direction that would match Erlang. This may be desirable, but I've taken the conservative route initially.
    3. See discussion Optimise codegen for constant segments in bit arrays on JS #3724 (comment) for more details.

Performance

Evaluating <<-1:32>>: 10-11x faster.

Evaluating a large lookup table of 16-bit integers: 26x faster.

Pattern matching a 32-bit signed integer: 2.7-7.1x faster, depending on how early a non-matching byte occurs.

Generated JavaScript code size is up to ~70% smaller. There are a few cases when using 40-bit and 48-bit wide integers that can see code size increases of ~20% with certain values, but the average case still sees a code size reduction on the wider integers.

@richard-viney richard-viney changed the title Compile-time evaluate constant bit array expressions/patterns on JavaScript Compile-time evaluate constant bit array int segments on JavaScript Nov 6, 2024
@richard-viney richard-viney changed the title Compile-time evaluate constant bit array int segments on JavaScript Compile-time evaluate constant BitArray int segments on JavaScript Nov 6, 2024
@richard-viney richard-viney force-pushed the eval-bit-array-ints branch 2 times, most recently from 4ce3ed8 to 4c7aaa0 Compare November 6, 2024 06:53
@richard-viney richard-viney marked this pull request as ready for review November 6, 2024 06:59
@richard-viney richard-viney force-pushed the eval-bit-array-ints branch 2 times, most recently from c00767f to c1593c6 Compare November 9, 2024 12:32
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Oooh very nice!!!

I've left some minor notes inline.

When you are ready for a review please un-draft this PR. Thank you!

compiler-core/Cargo.toml Show resolved Hide resolved
compiler-core/src/javascript.rs Outdated Show resolved Hide resolved
compiler-core/src/javascript.rs Outdated Show resolved Hide resolved
compiler-core/src/javascript.rs Outdated Show resolved Hide resolved
compiler-core/src/javascript.rs Outdated Show resolved Hide resolved
compiler-core/src/javascript/expression.rs Outdated Show resolved Hide resolved
compiler-core/src/javascript/tests/bit_arrays.rs Outdated Show resolved Hide resolved
<<4000:16>>
<<80_000:16>>
<<-80_000:16>>
<<-1:48>>
Copy link
Member

Choose a reason for hiding this comment

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

Only test one thing per test please.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@lpil lpil marked this pull request as draft November 19, 2024 15:38
@richard-viney richard-viney force-pushed the eval-bit-array-ints branch 6 times, most recently from 1dec85b to 453dc1b Compare November 20, 2024 20:26
@richard-viney richard-viney marked this pull request as ready for review November 20, 2024 20:31
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Fantastic! Thank you!

Seeing as this is tricky runtime behaviour could you add some integrations tests please 🙏

fn bit_array_tests() -> List(Test) {

@richard-viney
Copy link
Contributor Author

I've updated the existing language tests so each test is run both as a constant value that is compile-time evaluated, and as a dynamic value that is runtime evaluated.

Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

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

Amazing work again!!! 💜

@lpil lpil merged commit bd86469 into gleam-lang:main Nov 22, 2024
12 checks passed
@richard-viney richard-viney deleted the eval-bit-array-ints branch November 22, 2024 17: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