Skip to content

Conversation

@xunilrj
Copy link
Contributor

@xunilrj xunilrj commented Oct 10, 2025

Description

This is an optimisation of contract calls on top of #7440.

The old version would pass a string with the method name and encode it, which is <LEN><BYTES. Now the compiler generates these bytes directly, avoiding encoding the method name in the first place.

For that this PR creats the concept of Literal::Binary that does not exist in the language, yet. Would be something like b"" in Rust.

Improvements

Test Before After Percentage
should_pass/empty_fields_in_storage_struct (test.toml)::test_read_write_bytes 19298 17533 9.15%
should_pass/empty_fields_in_storage_struct (test.toml)::test_read_write_map 14971 13986 6.58%
should_pass/empty_fields_in_storage_struct (test.toml)::test_read_write_vec 31061 29288 5.71%
should_pass/language/associated_const_abi (test.toml)::test 8789 7817 11.06%
should_pass/language/associated_const_abi_multiple (test.toml)::test 2421 2097 13.38%
should_pass/language/associated_const_in_decls_of_other_constants (test.toml)::test 870 709 18.51%
should_pass/language/contract_caller_dynamic_address (test.toml) 540 379 29.81%
should_pass/language/contract_ret_intrinsic (test.toml)::test 2133 1809 15.19%
should_pass/language/pusha_popa_multiple_defreg (test.toml)::incorrect_pusha_popa 819 624 23.81%
should_pass/language/raw_identifiers (test.error_type.toml)::test 1236 1075 13.03%
should_pass/language/raw_identifiers (test.toml)::test 1236 1075 13.03%
should_pass/language/references/mutability_of_references_memcpy_bug (test.toml)::test 1364 1203 11.80%
should_pass/language/slice/slice_contract (test.toml)::test_success 1338 1145 14.42%
should_pass/language/string_slice/string_slice_contract (test.toml)::test_success 1515 1322 12.74%
should_pass/stdlib/storage_vec_insert (test.toml)::test_test_function 3992 3831 4.03%
should_pass/storage_element_key_modification (test.toml)::test_storage_key_address 1300 1138 12.46%
should_pass/storage_element_key_modification (test.toml)::test_storage_key_modification 919 757 17.63%
should_pass/storage_slot_key_calculation (test.toml)::test 3140 2979 5.13%
should_pass/superabi_contract_calls (test.toml)::tests 2136 1812 15.17%
should_pass/superabi_supertrait_same_methods (test.toml)::tests 1097 936 14.68%
should_pass/test_abis/abi_impl_methods_callable (test.toml)::tests 933 772 17.26%
should_pass/test_abis/contract_abi-auto_impl (test.toml)::tests 933 772 17.26%
should_pass/unit_tests/aggr_indexing (test.toml)::test1 6007 5443 9.39%
should_pass/unit_tests/contract-multi-contract-calls (test.toml)::test_contract_2_call 966 804 16.77%
should_pass/unit_tests/contract-multi-contract-calls (test.toml)::test_contract_call 969 807 16.72%
should_pass/unit_tests/contract-multi-contract-calls (test.toml)::test_contract_multi_call 1916 1592 16.91%
should_pass/unit_tests/contract_multi_test (test.toml)::test_fail 970 808 16.70%
should_pass/unit_tests/contract_multi_test (test.toml)::test_success 968 806 16.74%
should_pass/unit_tests/script-contract-calls (test.toml)::test_contract_call 931 736 20.95%
should_pass/unit_tests/workspace_test (test.toml)::test_fail 970 808 16.70%
should_pass/unit_tests/workspace_test (test.toml)::test_success 969 807 16.72%

Failed Test

Only now I realized that the test for array of size zero [u64; 0] is not working. As this is not a useful case, I will solve it in another PR.

Checklist

  • I have linked to any relevant issues.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have updated the documentation where relevant (API docs, the reference, and the Sway book).
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added (or requested a maintainer to add) the necessary Breaking* or New Feature labels where relevant.
  • I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
  • I have requested a review from the relevant team or maintainers.

@xunilrj xunilrj self-assigned this Oct 10, 2025
@codspeed-hq
Copy link

codspeed-hq bot commented Oct 10, 2025

CodSpeed Performance Report

Merging #7455 will not alter performance

Comparing xunilrj/improve-contract-call-2 (6832509) with master (fc2aed7)

Summary

✅ 25 untouched

@xunilrj xunilrj force-pushed the xunilrj/improve-contract-call-2 branch from d5df284 to 7d49ce3 Compare October 20, 2025 18:55
@xunilrj xunilrj marked this pull request as ready for review October 21, 2025 18:34
@xunilrj xunilrj requested review from a team as code owners October 21, 2025 18:34
@xunilrj xunilrj force-pushed the xunilrj/improve-contract-call-2 branch from e056208 to c1a5a19 Compare October 22, 2025 15:01
@xunilrj xunilrj marked this pull request as draft October 22, 2025 17:34
@xunilrj xunilrj marked this pull request as ready for review October 23, 2025 10:12
Copy link
Member

@ironcev ironcev left a comment

Choose a reason for hiding this comment

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

It would be interesting to see the performance comparison before and after the optimization, if it's not too much effort to generate it. I assume just pe2e and just pd should be sufficient to get it.

@xunilrj
Copy link
Contributor Author

xunilrj commented Oct 23, 2025

It would be interesting to see the performance comparison before and after the optimization, if it's not too much effort to generate it. I assume just pe2e and just pd should be sufficient to get it.

Done. See the description again.

@xunilrj xunilrj requested review from a team and ironcev October 23, 2025 17:11
Copy link
Member

@ironcev ironcev left a comment

Choose a reason for hiding this comment

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

The improvements numbers are great! 🚀

Copy link
Contributor

@zees-dev zees-dev left a comment

Choose a reason for hiding this comment

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

Suggested optional/minor nit.
LGTM! 👍🚀

@xunilrj xunilrj force-pushed the xunilrj/improve-contract-call-2 branch from 747d9e8 to 6832509 Compare October 26, 2025 09:28
@xunilrj xunilrj enabled auto-merge (squash) October 26, 2025 09:28
@xunilrj xunilrj merged commit 00b9d02 into master Oct 26, 2025
46 checks passed
@xunilrj xunilrj deleted the xunilrj/improve-contract-call-2 branch October 26, 2025 10:21
xunilrj added a commit that referenced this pull request Nov 4, 2025
## Description

This PR continues the optimisation of contract calls on top of
#7455. Now the contract method
selector is optimised. Ideally, the method selection would just be a
`match` and we would let the compiler generate the best code.

But we are not there yet. So, for now, we are going to first test the
called method length. And based on its length we are going to check the
whole string. Something like:

```sway
if called_method.len() == 5 {
    if called_method == "abcde" {
        ...
    }
    if called_method == "fghij" {
        ...
    }
}

if called_method.len() == 10 {
    if called_method == "..." {
        ....
    }
}
```

This alone reduces gas a lot.
To understand why `match_expressions_all` gas usage is much worse see
below.

| Test | Before | After | Percentage |
|------|--------|-------|------------|
| should_pass/empty_fields_in_storage_struct
(test.toml)::test_read_write_bytes | 17533 | 12080 | 31.10% |
| should_pass/empty_fields_in_storage_struct
(test.toml)::test_read_write_map | 13986 | 8502 | 39.21% |
| should_pass/empty_fields_in_storage_struct
(test.toml)::test_read_write_vec | 29288 | 12797 | 56.31% |
| should_pass/language/associated_const_abi (test.toml)::test | 7817 |
4547 | 41.83% |
| should_pass/language/associated_const_abi_multiple (test.toml)::test |
2097 | 1511 | 27.94% |
| should_pass/language/associated_const_in_decls_of_other_constants
(test.toml)::test | 709 | 537 | 24.26% |
| should_pass/language/contract_ret_intrinsic (test.toml)::test | 1809 |
1465 | 19.02% |
| should_pass/language/match_expressions_all (test.toml) | 764 | 3708 |
-385.34% |
| should_pass/language/pusha_popa_multiple_defreg
(test.toml)::incorrect_pusha_popa | 624 | 451 | 27.72% |
| should_pass/language/raw_identifiers (test.error_type.toml)::test |
1075 | 903 | 16.00% |
| should_pass/language/raw_identifiers (test.toml)::test | 1075 | 903 |
16.00% |
| should_pass/language/references/mutability_of_references_memcpy_bug
(test.toml)::test | 1203 | 1031 | 14.30% |
| should_pass/language/slice/slice_contract (test.toml)::test_success |
1145 | 920 | 19.65% |
| should_pass/language/string_slice/string_slice_contract
(test.toml)::test_success | 1322 | 1079 | 18.38% |
| should_pass/stdlib/storage_vec_insert (test.toml)::test_test_function
| 3831 | 3669 | 4.23% |
| should_pass/storage_element_key_modification
(test.toml)::test_storage_key_address | 1138 | 943 | 17.14% |
| should_pass/storage_element_key_modification
(test.toml)::test_storage_key_modification | 757 | 465 | 38.57% |
| should_pass/storage_slot_key_calculation (test.toml)::test | 2979 |
2785 | 6.51% |
| should_pass/superabi_contract_calls (test.toml)::tests | 1812 | 1310 |
27.70% |
| should_pass/superabi_supertrait_external_call (test.toml) | 95 | 76 |
20.00% |
| should_pass/superabi_supertrait_same_methods (test.toml)::tests | 936
| 634 | 32.26% |
| should_pass/test_abis/abi_impl_methods_callable (test.toml)::tests |
772 | 599 | 22.41% |
| should_pass/test_abis/contract_abi-auto_impl (test.toml)::tests | 772
| 599 | 22.41% |
| should_pass/unit_tests/aggr_indexing (test.toml)::test1 | 5443 | 4282
| 21.33% |
| should_pass/unit_tests/contract-multi-contract-calls
(test.toml)::test_contract_2_call | 804 | 631 | 21.52% |
| should_pass/unit_tests/contract-multi-contract-calls
(test.toml)::test_contract_call | 807 | 634 | 21.44% |
| should_pass/unit_tests/contract-multi-contract-calls
(test.toml)::test_contract_multi_call | 1592 | 1246 | 21.73% |
| should_pass/unit_tests/contract_multi_test (test.toml)::test_fail |
808 | 635 | 21.41% |
| should_pass/unit_tests/contract_multi_test (test.toml)::test_success |
806 | 633 | 21.46% |
| should_pass/unit_tests/script-contract-calls
(test.toml)::test_contract_call | 736 | 563 | 23.51% |
| should_pass/unit_tests/workspace_test (test.toml)::test_fail | 808 |
635 | 21.41% |
| should_pass/unit_tests/workspace_test (test.toml)::test_success | 807
| 634 | 21.44% |

# Radix Trie

This PR also turns off the radix trie optimisation at
`sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs`.
I am not 100% sure of its correctness and heuristics.

We need a better way to decide when not to use it. One of the examples
where the generated code is worse is when all strings are very similar.
For example: `get_a` , `get_b`. The generated trie will first test its
length. Both have length 5. Not much was gained. Then it tests if for
`get_`, which makes sense as it is the common substring. And the last
step will test for `a` or `b`.

The issue is that all branches and jumps of the last step are not worthy
to test just one character. Is probably cheaper to just test the whole
string for each option.

In the end, we need a better heuristic to determine when to use this
optimisation.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [ ] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have
[requested support from the DevRel
team](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [ ] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Joshua Batty <[email protected]>
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.

5 participants