Summary
On every DynamoDB request, AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext() invokes the full ExecutionInterceptorChain — including interceptors like DynamoDbResolveEndpointInterceptor and DynamoDbAuthSchemeInterceptor — even for work whose result is identical across all requests on the same client (endpoint resolution, auth scheme selection). Since the client configuration is immutable after build(), this work could be done once at construction time and reused.
Evidence
Using async-profiler on a JanusGraph server with a DynamoDB-heavy read workload (Query-dominated, ~thousands of DynamoDB calls/sec, SDK version 2.42.28):
| Method |
Cumulative CPU |
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext |
6.44% |
ExecutionInterceptorChain.modifyRequest |
2.00% |
ExecutionInterceptorChain$$Lambda_.accept |
1.75% |
ExecutionInterceptorChain.beforeExecution |
1.19% |
ExecutionInterceptorChain.modifyHttpRequestAndHttpContent |
0.91% |
The interceptor chain is executing on every request. For interceptors whose output depends only on static client configuration (endpoint, auth scheme, credentials provider type), this is redundant per-request work.
Specific interceptors doing static work per-request
Proposed fix
For interceptors whose modifyRequest output is a pure function of static client configuration, the SDK should either:
- Move that logic to a client construction-time step and cache the result, or
- Provide a mechanism for interceptors to declare themselves "static" so the framework can skip re-invoking them per request
This is consistent with the direction of PRs #6755 and #6820 (moving endpoint/auth-scheme resolution out of the interceptor framework into pipeline stages).
Related
Summary
On every DynamoDB request,
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContext()invokes the fullExecutionInterceptorChain— including interceptors likeDynamoDbResolveEndpointInterceptorandDynamoDbAuthSchemeInterceptor— even for work whose result is identical across all requests on the same client (endpoint resolution, auth scheme selection). Since the client configuration is immutable afterbuild(), this work could be done once at construction time and reused.Evidence
Using async-profiler on a JanusGraph server with a DynamoDB-heavy read workload (Query-dominated, ~thousands of DynamoDB calls/sec, SDK version 2.42.28):
AwsExecutionContextBuilder.invokeInterceptorsAndCreateExecutionContextExecutionInterceptorChain.modifyRequestExecutionInterceptorChain$$Lambda_.acceptExecutionInterceptorChain.beforeExecutionExecutionInterceptorChain.modifyHttpRequestAndHttpContentThe interceptor chain is executing on every request. For interceptors whose output depends only on static client configuration (endpoint, auth scheme, credentials provider type), this is redundant per-request work.
Specific interceptors doing static work per-request
DynamoDbResolveEndpointInterceptor(1.95% cum): re-evaluates the endpoint rules engine and re-parses the configured URI on every request, even whenendpointOverrideis set at construction time. See also DynamoDbResolveEndpointInterceptor re-evaluates endpoint rules engine on every request even when endpointOverride is static #6847.DynamoDbAuthSchemeInterceptor(~1.0% cum): re-resolves the auth scheme per request, despite the auth scheme being determined entirely by static client config.Proposed fix
For interceptors whose
modifyRequestoutput is a pure function of static client configuration, the SDK should either:This is consistent with the direction of PRs #6755 and #6820 (moving endpoint/auth-scheme resolution out of the interceptor framework into pipeline stages).
Related
ExecutionAttributesHashMap key hashing overhead (same parent hotspot)DynamoDbResolveEndpointInterceptorspecifically