Conversation
Some/most of these will be throaway like setting "requireEndpointResolver": false in build.gradle.kts.
Still lots of missing pieces
Condidtions generate, but not completely correctly. There are some compilation errors, mostly around Options where primitive types are expected. Coalesce works and is inlined.
Still a bug in Booleq and Stringeq with refs vs owned types.
TODO: impl results and fix the evaluate_bdd impl
Still need to add the tests
failures:
config::endpoint::test::test_134
config::endpoint::test::test_135
config::endpoint::test::test_139
config::endpoint::test::test_246
Had to bump Smithy version to 1.65 for it to work
…cument This was enabled by recent changes in Smithy that made function.type() work for BDD generation, so we can now get the output type.
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
|
A new generated diff is ready to view.
A new doc preview is ready to view. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: before this PR is actually merged it will need to have the S3 model reverted to the published one. Currently it has a custom S3 model with an
endpointBddTraitinstead just for CI testing/diff viewing purposes.Motivation and Context
Currently all AWS SDKs use a rules engine to resolve service endpoints before every operation. The current Endpoints 2.0 decision tree design creates significant problems that directly impact customers:
Larger SDK artifacts: S3's ruleset is 427 KB of JSON. The Rust SDK's generated resolver is 452 KB and nearly 6,000 lines of code. Customers download larger SDK packages and experience slower compilation times. Mobile and embedded applications face stricter size constraints that make AWS SDK adoption difficult.
Worse operation performance: Punishing fallback logic in decision tree evaluation requires 68 redundant condition checks for a simple S3 bucket+region endpoint. Customers experience slower operation initialization, particularly in serverless environments where cold starts are critical.
Description
This PR implements code generation for the new
endpointBddtrait, which uses Binary Decision Diagrams (BDDs) to optimize endpoint resolution. BDDs provide a more compact representation of endpoint rules compared to the existingendpointRuleSettrait, reducing binary size and improving resolution performance. More information about the new trait can be found on the Smithy website: https://smithy.io/2.0/additional-specs/rules-engine/specification.html#smithy-rules-endpointbdd-traitThe entrypoint to the code generation is in
EndpointsDecorator.ktwhere, if anendpointBddtrait exists, it is prioritized over theendpointRuleSettrait. This invokes theEndpointBddGeneratorwhich orchestrates most of the code generation. The functions in the match arms of each of the condition blocks are generated by theBddExpressionGeneratorclass. The most recent diff of this generated code is available here.The most notable new Rust code lives in the
rust-runtime/inlineable/crate:endpoint_lib/bdd_interpreter.rscontains theevaluate_bddfunction used to actually traverse the BDD DAG and extract a Result.endpoint_lib/coalesce.rsexports a newcoalesce!macro that implements the new endpoint std lib coalesce function. Note that the macro here uses a technique called autoderef-based specialization and was inspired by this blog post: https://lukaskalbertodt.github.io/2019/12/05/generalized-autoref-based-specialization.htmlDiving deeper into the code in the diff there are a few important new types to discuss:
struct BddNodecontaining thecondition_index,high_ref, andlow_ref.enum ConditionFnto represent the functions for evaluating each condition.enum ResultEndpointto represent the functions for generating each result.struct ConditionContextto represent variables that can be assigned by ConditionsFor each of
BddNode,ConditionFn, andResultEndpointthere is a constant sized array containing instances of each so they can be referenced by index:ConditionFnimplements a single function,evaluate, that takes in the modeled endpoint Params and theConditionContextfor passing around state between different condition evaluations, and a diagnostic_collector for tracking data about the evaluation.ResultEndpointalso implements a single functionto_endpointthat either returns anEndpointor aResolveEndpointErrordepending on which result index is passed. Note that index 0 corresponds to theNoMatchRuleThe final important portion of our resolver is the
evaluate_bddfunction. This function is handwritten and will work with the generated nodes, conditions, and results for each service. This function takes 4 generic types:Condfor the generated conditions,Paramsfor the modeled endpoint params,Resfor the generated results, andContextfor the shared condition context.TODO: There are a few tasks left for the BDD work to be fully complete:
endpointBddtraits. This work in being done as part of the SEP process and will come in a subsequent PR.aws_sdk_s3::config::endpoint::ResultEndpoint::to_endpointsymbol is still the largest one in my test binary. I would like to experiment with reducing the size there. This could look like splitting the match arms into separate functions, but a quick POC of that approach slightly increased the overall binary size even though it did reduce the size of the largest symbol.Testing
New minimal tests introduced for BDD, more to come as the SEP is fleshed out and I manage to compile some of the existing tests to BDD format.
Note: A few tests here are failing, I'm pretty all of those are due to differences in the S3 model I am using. I borrowed it from smithy-java and it was missing a few things (like
Bodymembers on some input/output types).Note: More codegen tests will be introduced as the SEP is finalized and more tests are converted to BDD format.
In addition to the new tests I performed various benchmarks against the S3 test suite. The raw data is too large to include here, but across the 347 tests in the S3 model the average speedup compared to the previous tree based generation was ~55%.
Checklist
.changelogdirectory, specifying "client," "server," or both in theapplies_tokey..changelogdirectory, specifying "aws-sdk-rust" in theapplies_tokey.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.