|
| 1 | +# DynamoDB Performance Benchmarks |
| 2 | + |
| 3 | +Manual-first DynamoDB suite in `sdk-benchmarks`. New Tier C / Tier D classes are **not** selected by |
| 4 | +`BenchmarkRunner`, shards, baselines, or CI. |
| 5 | + |
| 6 | +Results across tiers answer different questions and must **not** be compared as one score. |
| 7 | + |
| 8 | +## Measurement tiers |
| 9 | + |
| 10 | +| Tier | What it measures | What it excludes | |
| 11 | +|---|---|---| |
| 12 | +| **A** — Pure micro / protocol | Marshalling, JSON protocol, schema/JSON conversion, cold start | Full client pipeline, network | |
| 13 | +| **B** — Mapper isolation | Enhanced mapping via stub `V2TestDynamoDb*Client` | Marshalling, signing, HTTP, network | |
| 14 | +| **C** — Mocked pipeline *(new)* | Full sync/async SDK client path with deterministic mock HTTP | Network and DynamoDB service latency | |
| 15 | +| **D** — Live DynamoDB *(new)* | End-to-end path: SDK + HTTP transport + **network latency** + **DynamoDB service latency** + response handling | Table provisioning, seeding, client/fixture construction (those stay in `@Setup` / `@TearDown`, outside the timed `@Benchmark` method) | |
| 16 | + |
| 17 | +Packages: |
| 18 | + |
| 19 | +- Tier C: `software.amazon.awssdk.benchmark.dynamodb.pipeline` |
| 20 | +- Tier D: `software.amazon.awssdk.benchmark.dynamodb.live` |
| 21 | +- Shared: `…dynamodb.fixture`, `…dynamodb.mock`, `DynamoDbBenchmarkConstant` |
| 22 | + |
| 23 | +## Client layers (LOW / DOCUMENT / TYPED) |
| 24 | + |
| 25 | +These labels are an analysis taxonomy for the suite, not official AWS client product names: |
| 26 | + |
| 27 | +| Layer | API surface | What the timed path emphasizes | |
| 28 | +|---|---|---| |
| 29 | +| **LOW** | `DynamoDbClient` / `DynamoDbAsyncClient` | Direct DynamoDB request/response (pre-built low-level requests in sync Get/Put) | |
| 30 | +| **DOCUMENT** | `DynamoDbTable<EnhancedDocument>` | Enhanced Document model over the same logical item | |
| 31 | +| **TYPED** | `DynamoDbTable<BenchmarkItem>` (bean mapping) | Enhanced typed mapping to/from the shared fixture bean | |
| 32 | + |
| 33 | +LOW, DOCUMENT, and TYPED reuse the same logical fixture and keys so cross-layer comparisons stay fair within a tier. |
| 34 | + |
| 35 | +## Inventory (implemented) |
| 36 | + |
| 37 | +| Tier | Layer | Sync/Async | Operations | |
| 38 | +|---|---|---|---| |
| 39 | +| A | Protocol / micro | Sync (existing) | Existing marshaller / protocol / cold-start benches | |
| 40 | +| B | TYPED mapper isolation | Sync (existing) | Get/Put/Query/Update/Delete/Scan via stub clients | |
| 41 | +| C | LOW | Sync | GetItem, PutItem | |
| 42 | +| C | DOCUMENT | Sync | GetItem, PutItem | |
| 43 | +| C | TYPED | Sync | GetItem, PutItem, Query (first page) | |
| 44 | +| C | LOW | Async | GetItem (`.join()`) | |
| 45 | +| C | TYPED | Async | GetItem (`.join()`) | |
| 46 | +| D | LOW | Sync | GetItem, PutItem | |
| 47 | +| D | TYPED | Sync | GetItem, PutItem, Query (first page) | |
| 48 | + |
| 49 | +Deferred by design: DOCUMENT async, LOW Query, async Put/Query, concurrency, Batch/Transact, CI/shards/baselines. |
| 50 | + |
| 51 | +## JMH modes |
| 52 | + |
| 53 | +| Family | Mode | Unit | Defaults | |
| 54 | +|---|---|---|---| |
| 55 | +| Tier C (`pipeline`) | `AverageTime` | µs/op | warmup 5 / measurement 5 / forks 2 | |
| 56 | +| Tier D (`live`) | `SampleTime` | ms/op | warmup 3 / measurement 5 / fork 1 | |
| 57 | + |
| 58 | +Reduced CLI overrides (`-wi 1 -i 1 -f 1`) are fine for smoke checks. Use class defaults for meaningful comparisons. |
| 59 | + |
| 60 | +## Manual build and run |
| 61 | + |
| 62 | +From the repository root: |
| 63 | + |
| 64 | +```bash |
| 65 | +mvn clean install -P quick -pl :sdk-benchmarks --am |
| 66 | +cd test/sdk-benchmarks |
| 67 | +``` |
| 68 | + |
| 69 | +List DynamoDB-related benchmarks: |
| 70 | + |
| 71 | +```bash |
| 72 | +# Windows (cmd / PowerShell) |
| 73 | +java -jar target/benchmarks.jar -l | findstr /i dynamodb |
| 74 | + |
| 75 | +# Unix-like (macOS / Linux / Git Bash) |
| 76 | +java -jar target/benchmarks.jar -l | grep -i dynamodb |
| 77 | +``` |
| 78 | + |
| 79 | +### Tier C (mocked — no AWS) |
| 80 | + |
| 81 | +```bash |
| 82 | +# All Tier C pipeline benches |
| 83 | +java -jar target/benchmarks.jar "software.amazon.awssdk.benchmark.dynamodb.pipeline" |
| 84 | + |
| 85 | +# LOW |
| 86 | +java -jar target/benchmarks.jar ".*pipeline.LowLevel" |
| 87 | + |
| 88 | +# DOCUMENT |
| 89 | +java -jar target/benchmarks.jar ".*pipeline.Document" |
| 90 | + |
| 91 | +# TYPED |
| 92 | +java -jar target/benchmarks.jar ".*pipeline.Typed" |
| 93 | + |
| 94 | +# Async Get only |
| 95 | +java -jar target/benchmarks.jar ".*pipeline.*Async" |
| 96 | + |
| 97 | +# Single class |
| 98 | +java -jar target/benchmarks.jar LowLevelGetItemBenchmark |
| 99 | +``` |
| 100 | + |
| 101 | +### Tier D (live — opt-in required) |
| 102 | + |
| 103 | +```bash |
| 104 | +# PowerShell |
| 105 | +$env:DYNAMODB_BENCHMARK_LIVE="true" |
| 106 | +$env:AWS_REGION="us-east-1" # or rely on the default AWS region chain / DYNAMODB_BENCHMARK_REGION |
| 107 | + |
| 108 | +java -jar target/benchmarks.jar "software.amazon.awssdk.benchmark.dynamodb.live" |
| 109 | + |
| 110 | +# Equivalent system property |
| 111 | +java -Ddynamodb.benchmark.live=true -jar target/benchmarks.jar "software.amazon.awssdk.benchmark.dynamodb.live" |
| 112 | +``` |
| 113 | + |
| 114 | +Region override (optional): |
| 115 | + |
| 116 | +```bash |
| 117 | +$env:DYNAMODB_BENCHMARK_REGION="us-west-2" |
| 118 | +# or: -Ddynamodb.benchmark.region=us-west-2 |
| 119 | +``` |
| 120 | + |
| 121 | +### JSON output and profiling |
| 122 | + |
| 123 | +```bash |
| 124 | +java -jar target/benchmarks.jar LowLevelGetItemBenchmark -rf json -rff results.json |
| 125 | +java -jar target/benchmarks.jar LowLevelGetItemBenchmark -prof gc |
| 126 | +``` |
| 127 | + |
| 128 | +## Live safety |
| 129 | + |
| 130 | +- AWS credentials are required (`DefaultCredentialsProvider`). |
| 131 | +- Opt-in is mandatory: `DYNAMODB_BENCHMARK_LIVE=true` or `-Ddynamodb.benchmark.live=true`. |
| 132 | + Without it, `@Setup` aborts **before** credential resolution, client construction, or any AWS call. |
| 133 | + (System property takes precedence over the environment variable if both are set.) |
| 134 | +- Each trial creates a **unique** table: `sdk-java-ddb-perf-{op}-{8hex}`. |
| 135 | +- Billing mode: **PAY_PER_REQUEST**. |
| 136 | +- Tables are tagged (`sdk-java-ddb-perf-benchmark=owned`, `Purpose=aws-sdk-java-v2-dynamodb-live-benchmark`) so orphans from interrupted runs can be identified. |
| 137 | +- Teardown deletes **only** the exact table created by that trial (`createdByThisTrial`). |
| 138 | +- Interrupted runs (kill/OOM) may leave orphaned tagged tables — clean up manually if needed. |
| 139 | +- Live runs incur DynamoDB request cost and service/network variance. |
| 140 | + |
| 141 | +Retry observation (default on): a lightweight `ExecutionInterceptor` counts attempts. Disable with |
| 142 | +`DYNAMODB_BENCHMARK_LIVE_RETRY_OBSERVE=false` / `-Ddynamodb.benchmark.live.retryObserve=false`. |
| 143 | +Default SDK retry policy is unchanged. Runs with retries print a warning — interpret scores carefully. |
| 144 | + |
| 145 | +## Interpretation |
| 146 | + |
| 147 | +- **Tier C** is deterministic SDK-side cost (mock HTTP). Best signal for SDK regressions. |
| 148 | +- **Tier D** includes network and DynamoDB latency. Use for directional E2E checks, not µs SDK diffs. |
| 149 | +- **LOW vs TYPED** under Tier D is directional only (service variance dominates). |
| 150 | +- **Async** single-op benches include mock/async executor scheduling and `.join()` completion. |
| 151 | +- Untimed smoke calls (DNS/TLS/pool init on live; pipeline warm on mocked) are **not** JMH warmup |
| 152 | + iterations — JMH still runs its own warmup afterward. |
| 153 | + |
| 154 | +## Automation invariant |
| 155 | + |
| 156 | +Do **not** add these classes to `BenchmarkRunner`, shards, `baseline.json`, or CI without an explicit |
| 157 | +follow-up design. `mvn package` / `exec:exec` behavior for existing suites is unchanged. |
0 commit comments